Library for caching data:
- In memory (using Caffeine) or with a centralized cache (Redis using Lettuce Reactive) making a single tier cache.
- Or using both as a two tier stage cache.
- Installation process
For local cache only
dependencies {
implementation 'com.github.bancolombia:bin-stash-local:<version>'
}
For a centralized (redis) cache only
dependencies {
implementation 'com.github.bancolombia:bin-stash-centralized:<version>'
}
For an hybrid (local and centralized) cache
dependencies {
implementation 'com.github.bancolombia:bin-stash-hybrid:<version>'
}
- Supported Configuration
stash:
memory:
expireTime: 60 # 1 minute
maxSize: 10_000
redis:
host: myredis.host
# Only when connecting to a master/replica
#replicas: replica.myredis.host, replica2.myredis.host
port: 6379
database: 0
# for rbac access
username: myuser
password: mypwd
useSsl: true
expireTime: 3600 # 1 hour
Configuration | Description |
---|---|
stash.memory.maxSize | maximum allowed bytes to store in memory cache |
stash.memory.expireTime | set maximum time to hold keys in cache (in seconds). If not defined, a value of 300 seconds is used as default. Note that save() methods that receive a TTL argument, will ignore such value if its greater than expireTime . |
stash.redis.host | host to connect to (when connecting to a master-replica cluster this is the master host) |
stash.redis.replicas | host names of replicas, comma separated. (when connecting to a master-replica cluster) |
stash.redis.port | redis port (when connecting to master-replicas will use same port for all hosts) |
stash.redis.database | database number to use on single node (0 default) |
stash.redis.username | username (when using RBAC) |
stash.redis.password | password when using AUTH or RBAC |
stash.redis.useSsl | true or false. Indicates the client to connect to redis via secure connection |
stash.redis.expireTime | default TTL time (in seconds) to hold every key stored in redis. If this parameter is not defined a default value of 300 seconds is used. This value can be overriden for an specific key, with the TTL argument in the save() methods. |
-
Usage
3.1. For Local Cache
@Configuration public class LocalExampleConfiguration { @Bean public ObjectMapper objectMapper() { return new ObjectMapper(); } @Bean public ObjectCache<Person> objectCache(LocalCacheFactory<Person> localCacheFactory) { return localCacheFactory.newObjectCache(); } }
3.2. For Centralized Cache
@Configuration public class CentralizedExampleConfiguration { [...] @Bean public ObjectCache<Person> objectCache(CentralizedCacheFactory<> centralizedCacheFactory) { return centralizedCacheFactory.newObjectCache(); } }
3.3. For Hybrid Cache
@Configuration public class HybridExampleConfiguration { [...] @Bean public List<SyncRule> cacheSyncRules() { // Just one rule in this demo. Push local cache key-values to centralized cache, disregarding syncType // (UPSTREAM or DOWNSTREAM) and pull centralized cache key-values to local cache when affected // key (keyArg) is ANY string. SyncRule simpleSyncRule = (keyArg, syncType) -> true; return Collections.singletonList(simpleSyncRule); } @Bean public ObjectCache<Person> objectCache(HybridCacheFactory<Person> cacheFactory, List<SyncRule> cacheSyncRules) { return cacheFactory.newObjectCache(cacheSyncRules); } }
You can now use ObjectCache<>
in your app:
@Component
public class PersonCachedHandler {
public final DummyRepo dummyRepo;
public final ObjectCache<Person> cache;
@Autowired
public PersonCachedHandler(DummyRepo dummyRepo,
ObjectCache<Person> cache) {
this.dummyRepo = dummyRepo;
this.cache = cache;
}
public Mono<ServerResponse> fetchWithCache(ServerRequest request) {
String key = Optional.of(request.pathVariable("id"))
.orElse("JhonSmith1");
// Usage with reactor-extra CacheMono
Mono<Person> cached = CacheMono
.lookup(k -> cache.get(k, Person.class) // Get from cache
.map(Signal::next), key)
.onCacheMissResume(dummyRepo.findByName(key)) // Get from some db repo
.andWriteWith((k, sig) ->
cache.save(k, sig.get()).then() // Save to cache
);
return cached
.flatMap(person -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(person))
);
}
}
- Latest releases
- API references
When using the cache in hybrid mode (two tier cache), requests works as described:
GET Operation
- When a lookup misses local cache, and upstream sync is allowed, bin-stash tries to lookup in the centralized cache.
- If the lookup operation in the centralized cache hits a key, then return the value. Also if downtream sync is allowed, the key-value is replicated in local cache.
SAVE operation
- Writes are performed in local cache, and if upstream sync is allowed, bin-stash tries to write key-value in the centralized cache, given this key doesn't previously exists.
EVICT operation
Evict(key)
is performed in local cache, and if upstream sync is allowed, bin-stash tries to evict key-value in the centralized cache.EvictAll
operation it's performed on local and is not syncronized upstream.
Sync Rules
DoubleTierCache uses a collection of SyncRule
to determine if upstream/downstream sync takes place.
This functional interface takes keyname and SyncType
(UPSTREAM or DOWNSTREAM) as arguments, and should return
a boolean
.
TODO: Describe and show how to build your code and run the tests.
TODO: Explain how other users and developers can contribute to make your code better.