# Caching

Source: https://orbitalhq.com/docs/querying/caching

## Caching requests
By default, Orbital will cache requests throughout a query only. ie., Orbital will only call a service with the same set of
parameters once within a query.

However, caches are destroyed at the end of each query.

To enable caching, simply add `@Cache` to the top of your query:

```taxi
> @Cache
  find { Film[] } as {
    id : FilmId
    // Fetched from a remote service.
    // Calls will be cached.
    currentReviewScore : ReviewScore
  }
```

### Scoping caches
By default, all queries share the same cache.  If you want cache isolation, so that
population and invalidation are isolated from each other, you can apply a name to the cache:

```taxi
> @Cache("myCache")
  find { Film[] } as {
    id : FilmId
    // Fetched from a remote service.
    // Calls will be cached.
    currentReviewScore : ReviewScore
  }
```

## Using Orbital's local cache
Orbital's local cache runs in-process within Orbital.  

It's the default cache that's enabled if no connection is provided.

It's helpful for development, but shouldn't be taken to production,
as excessive caching can cause Out-of-Memory failures and degrade performance.

```taxi
  // This query uses the default, local cache
> import com.orbitalhq.caching.Cache
> @Cache
  find { Film[] } as {
    id : FilmId
    // Fetched from a remote service
    currentReviewScore : ReviewScore
  }
```

## Caching and streams
Operations that return streams are never cached

## Preventing caching
Caching can be prevented either on an operation, or a response model, by specifying a `mode = CachePolicy.Disabled`.

For example, to disable caching on all responses from a specific operation:

```taxi
> import com.orbitalhq.caching.Cache

  service PersonApi {
      // Responses from this operation are never cached.
>     @Cache(mode = CachePolicy.Disabled)
      operation getAccount(AccountId):AccountState
   }
```

Or, to prevent caching on a model:

```taxi
> import com.orbitalhq.caching.Cache

> @Cache(mode = CachePolicy.Disabled)
  model AccountState {
    // implementaion omitted
  }

  service AccountApi {
    // The result of this call isn't cached, 
    // as it's prevented on the model definition
    operation getAccount(AccountId):AccountState
  }
```

When defining cache controls on a model, only cache controls on the top-level entity are considered.

## Cache TTL

Responses written to a cache have a default TTL of 5 minutes. You can control this by setting a 
[cache-level TTL](#cache-ttl-1).

Orbital will also honour the [max-age](#max-age-headers) in response headers.

### Fine-grained cache control
TTL can be controlled by setting the `maxIdleSeconds` on either an operation, or a return type.

For example:

```taxi
> import com.orbitalhq.caching.Cache

  service PersonApi {
      // Responses from this operation are evicted after not being read or 
      // written for 30 seconds
>     @Cache(maxIdleSeconds = 30)
      operation getAccount(AccountId):AccountState
   }
```

Alternatively, controls can be applied on the model:

```taxi
> import com.orbitalhq.caching.Cache

> @Cache(maxIdleSeconds = 30)
  model AccountState {
    // implementaion omitted
  }

  service AccountApi {
     // Responses from this operation are evicted after not being read or 
     // written for 30 seconds
    operation getAccount(AccountId):AccountState
  }
```

### max-age headers
Orbital will honour max-age headers when caching responses from HTTP services:

Setting the `cache-control: max-age=` header will cause the entry to be automatically evicted after the `max-age` expires.

## Using an external cache
Orbital supports external caches, and will run a near-cache in-process, offloading to the remote cache
as the library supports.

To enable a remote cache, first define a connection to the cache in your `connections.conf` file, then specify
the name of the connection in your query.

```hocon connections.conf
hazelcast {
   myHazelcast {
      connectionName = myHazelcast
      addresses = ["localhost:5701"]
   }
}
```

```taxi query.taxi
> @Cache(connection = "myHazelcast")
  find { Film[] } as {
    id : FilmId
    // Fetched from a remote service
    currentReviewScore : ReviewScore
  }
```

### Supported caches
Orbital supports caching with the following platforms:

 * Hazelcast
 * Redis

If you need cache not listed, please [reach out on slack](https://join.slack.com/t/orbitalapi/shared_invite/zt-697laanr-DHGXXak5slqsY9DqwrkzHg)

### Cache TTL
The default Cache TTL is defined in the connections file:

```hocon connections.conf
  hazelcast {
     myHazelcast {
        connectionName = myHazelcast
        addresses = ["localhost:5701"]
>       ttl = 20 minutes
     }
  }
```
