V - the value type@PublicApi public interface ExternalCache<V> extends VCache
MarshallingPair.
The settings provided when creating a ExternalCache are only used within the JVM and are not
centrally stored across JVMs.
Failures are expected to happen when communicating with the external system, and the caller is expected to
deal with them. As such, all operations that involve communicating with the external system will return an
CompletionStage, which encapsulates that failure may have occurred.
Any returned CompletionStage is guaranteed to complete by the end of the Atlassian WorkContext it was
created within. There is no need to explicitly "join" on a CompletionStage,
using VCacheUtils.fold(CompletionStage, Function, Function) or similar. This means that any "connected"
CompletionStage, via CompletionStage.thenCombine(CompletionStage, BiFunction) etc, will be
performed.
Buffering of communications to the external cache system may be applied to both read and write operations.
The following three specialisations of the ExternalCache are provided to represent the possible
buffering modes:
DirectExternalCache - buffering is not applied for either read or write operations.TransactionalExternalCache - buffering is applied for both read and write operations.StableReadExternalCache - buffering is applied for only read operations
Buffering of read operations means that the result of every read operation
is stored in a private RequestCache. All read operations will first query the private
RequestCache to determine whether the operation has been performed before, and if it has, return the
buffered result.
Buffering of write operations means that all write operations are stored
in a private RequestCache, and at the end of the transaction they are applied to the
external cache system.
When buffering is used for write operations, the issue arises as to how to handle when there are conflicts when replaying the buffered operations. The guiding principles are:
All read operations, even if buffered, may involve failures. As such, all read operations are encapsulated in this interface. However, buffered write operations will not expose failures as they are replayed later. Hence, the write operations are provided through the following two interfaces which are used by the four specialisations of this interface:
ExternalWriteOperationsBuffered - encapsulates the buffered versions of the write operations.ExternalWriteOperationsUnbuffered - encapsulates the unbuffered versions of the write operations.
The operations that may create values using a supplied Supplier or Function
make no guarantees about their atomicity. There is a possible race condition between detecting
that a value is missing in the external cache system, and the generated value being stored
in the external cache system. The implementations are free to override any (new) value that
may have been stored in the external cache system. If this behaviour is unacceptable, then
the caller is responsible for using a strategy to deal with this (such as global locking).
Duration.
The implementations may round-up the supplied ttl to the nearest second. E.g. 500 milliseconds may be
converted to 1 second.
As the data is stored externally to the JVM, the following needs to be considered:
MarshallingPair instance for marshalling values.
By extension, this means that an ExternalCache can only be used for data that can be marshalled
to/from byte arrays.
Each cache is configured with the following hints to allow the implementation the opportunity to optimise performance.
ExternalCacheSettings.getDataChangeRateHint() - this is a hint on the expected rate of change to the
data held in the cache, including updating existing entries. A cache that holds values that are never
updated after being populated should use ChangeRate.NONE. A cache that holds data that changed
infrequently, like a cache of project details, should use ChangeRate.LOW_CHANGE.
ExternalCacheSettings.getEntryGrowthRateHint() - this is a hint on the expected rate of change in
the number of entries held in the cache. A cache that holds a fixed number of entries should
use ChangeRate.NONE.
ExternalCacheSettings.getEntryCountHint() - this is a hint on the desired number of entries in
the cache. The implementation is free to use this as it sees fit.
| Modifier and Type | Method and Description |
|---|---|
CompletionStage<Optional<V>> |
get(String key)
Returns a value that is associated with a specified key.
|
CompletionStage<V> |
get(String key,
Supplier<V> supplier)
Returns a value that may be associated with a specified key.
|
CompletionStage<Map<String,V>> |
getBulk(Function<Set<String>,Map<String,V>> factory,
Iterable<String> keys)
Returns the values that are associated with the specified keys.
|
default CompletionStage<Map<String,V>> |
getBulk(Function<Set<String>,Map<String,V>> factory,
String... keys)
Returns the values that are associated with the specified keys.
|
CompletionStage<Map<String,Optional<V>>> |
getBulk(Iterable<String> keys)
Returns the values that are associated with the specified keys.
|
default CompletionStage<Map<String,Optional<V>>> |
getBulk(String... keys)
Returns the values that are associated with the specified keys.
|
CompletionStage<Optional<V>> get(String key)
key - the key to check.Optional which may contain the value associated with the key.CompletionStage<V> get(String key, Supplier<V> supplier)
Notes:
key - the key uniquely identifying the value to be retrievedsupplier - used to generate the value, if one does not exist already for the key. The supplier may not
return null.default CompletionStage<Map<String,Optional<V>>> getBulk(String... keys)
getBulk(Iterable) passing Arrays.asList(keys) as the parameter.CompletionStage<Map<String,Optional<V>>> getBulk(Iterable<String> keys)
default CompletionStage<Map<String,V>> getBulk(Function<Set<String>,Map<String,V>> factory, String... keys)
getBulk(Function, Iterable) passing factory and Arrays.asList(keys) as the parameters.
Notes:
factory - used to generate the values for the keys that do not have entries. The factory must return a
map containing a non-null entry for each supplied key.keys - the keys to retrieveMap that is keyed on the keys specified. Each entry in the Map will have
the value associated with the key.CompletionStage<Map<String,V>> getBulk(Function<Set<String>,Map<String,V>> factory, Iterable<String> keys)
Notes:
factory - used to generate the values for the keys that do not have entries. The factory must return a
map containing a non-null entry for each supplied key.keys - the keys to retrieveMap that is keyed on the keys specified. Each entry in the Map will have
the value associated with the key.Copyright © 2016 Atlassian. All rights reserved.