diff --git a/docs/README.md b/docs/README.md
index 5f4fedcbf..435087ce9 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,4 +1,4 @@
-# Redisson - Easy Redis Java client
and Real-Time Data Platform
+# Redisson - Valkey & Redis Java client
Complete Real-Time Data Platform
High-performance async and lock-free Java client for Redis and Valkey based on [Netty](http://netty.io) framework.
diff --git a/docs/data-and-services/collections.md b/docs/data-and-services/collections.md
index da9bf04b7..c973ed873 100644
--- a/docs/data-and-services/collections.md
+++ b/docs/data-and-services/collections.md
@@ -667,15 +667,32 @@ multimap.destroy();
_This feature is available only in [Redisson PRO](https://redisson.pro) edition._
-Distributed Java implementation of Redis or Valkey based Key Value store for JSON objects. This object is thread-safe. Allows to store JSON value mapped by key. Operations can be executed per key or group of keys. Value is stored/retrieved using `JSON.*` commands. Both key and value are POJO objects.
+[RJsonStore](https://www.javadoc.io/doc/org.redisson/redisson/latest/org/redisson/api/RJsonStore.html) is a distributed Key Value store for JSON objects. Compatible with Redis or Valkey. This object is thread-safe. Allows to store JSON value mapped by key. Operations can be executed per key or group of keys. Value is stored/retrieved using `JSON.*` commands. Both key and value are POJO objects.
Allows to define `time to live` parameter per entry. Doesn't use an entry eviction task, entries are cleaned on Redis or Valkey side.
-Implements **Async**, **Reactive** and **RxJava3** interfaces.
+Code example of **[Async](https://www.javadoc.io/doc/org.redisson/redisson/latest/org/redisson/api/RJsonStoreAsync.html) interface** usage:
+
+```java
+RJsonStoreAsync store = redisson.getJsonStore("test", new JacksonCodec(MyObject.class));
+```
+
+Code example of **[Reactive](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RJsonStoreReactive.html) interface** usage:
+
+```java
+RedissonReactiveClient redisson = redissonClient.reactive();
+RJsonStoreReactive bucket = redisson.getJsonStore("anyObject", new JacksonCodec<>(AnyObject.class));
+```
+
+Code example of **[RxJava3](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RJsonStoreRx.html) interface** usage:
+```java
+RedissonRxClient redisson = redissonClient.rxJava();
+RJsonStoreRx bucket = redisson.getJsonStore("anyObject", new JacksonCodec<>(AnyObject.class));
+```
Data write code example:
```java
-RJsonStore store = redisson.getJsonStore("test", StringCodec.INSTANCE, new JacksonCodec(MyObject.class));
+RJsonStore store = redisson.getJsonStore("test", new JacksonCodec(MyObject.class));
MyObject t1 = new MyObject();
t1.setName("name1");
@@ -705,7 +722,7 @@ store.setIfExists("1", t1);
Data read code example:
```java
-RJsonStore store = redisson.getJsonStore("test", StringCodec.INSTANCE, new JacksonCodec(MyObject.class));
+RJsonStore store = redisson.getJsonStore("test", new JacksonCodec(MyObject.class));
// multiple entries at once
Map entries = store.get(Set.of("1", "2"));
@@ -717,7 +734,7 @@ MyObject value2 = store.get("2");
Data deletion code example:
```java
-RJsonStore store = redisson.getJsonStore("test", StringCodec.INSTANCE, new JacksonCodec(MyObject.class));
+RJsonStore store = redisson.getJsonStore("test", new JacksonCodec(MyObject.class));
// multiple entries at once
long deleted = store.delete(Set.of("1", "2"));
@@ -727,7 +744,22 @@ boolean status = store.delete("1");
boolean status = store.delete("2");
```
-For data searching index prefix should be defined in `:` format. For example for object name "test" prefix is "test:".
+Keys access code examples:
+```java
+RJsonStore store = redisson.getJsonStore("test", new JacksonCodec(MyObject.class));
+
+// iterate keys
+Set keys = store.keySet();
+
+// read all keys at once
+Set keys = store.readAllKeySet();
+```
+
+### Search by Object properties
+
+For data searching, index prefix should be defined in `:` format. For example for object name "test" prefix is "test:".
+
+`StringCodec` should be used as object codec to enable searching by field.
Data search code example:
```java
@@ -758,17 +790,6 @@ AggregationResult ar = s.aggregate("idx", "*", AggregationOptions.defaults()
.withCursor().load("name"));
```
-Keys access code examples:
-```java
-RJsonStore store = redisson.getJsonStore("test", StringCodec.INSTANCE, new JacksonCodec(MyObject.class));
-
-// iterate keys
-Set keys = store.keySet();
-
-// read all keys at once
-Set keys = store.readAllKeySet();
-```
-
### Local Cache
Redisson provides [JSON Store](#json-store) implementation with local cache.
@@ -912,54 +933,6 @@ boolean status = store.delete("1");
boolean status = store.delete("2");
```
-For data searching index prefix should be defined in `:` format. For example for object name "test" prefix is "test:".
-
-Data search code example:
-```java
-RSearch s = redisson.getSearch();
-s.createIndex("idx", IndexOptions.defaults()
- .on(IndexType.JSON)
- .prefix(Arrays.asList("test:")),
- FieldIndex.text("name"));
-
-LocalCachedJsonStoreOptions ops = LocalCachedJsonStoreOptions.name("test")
- .keyCodec(StringCodec.INSTANCE)
- .valueCodec(new JacksonCodec<>(MyObject.class));
-RLocalCachedJsonStore store = redisson.getLocalCachedJsonStore(ops);
-
-MyObject t1 = new MyObject();
-t1.setName("name1");
-MyObject t2 = new MyObject();
-t2.setName("name2");
-
-Map entries = new HashMap<>();
-entries.put("1", t1);
-entries.put("2", t2);
-store.set(entries);
-
-// search
-SearchResult r = s.search("idx", "*", QueryOptions.defaults()
- .returnAttributes(new ReturnAttribute("name")));
-
-// aggregation
-AggregationResult ar = s.aggregate("idx", "*", AggregationOptions.defaults()
- .withCursor().load("name"));
-```
-
-Keys access code examples:
-```java
-LocalCachedJsonStoreOptions ops = LocalCachedJsonStoreOptions.name("test")
- .keyCodec(StringCodec.INSTANCE)
- .valueCodec(new JacksonCodec<>(MyObject.class));
-RLocalCachedJsonStore store = redisson.getLocalCachedJsonStore(ops);
-
-// iterate keys
-Set keys = store.keySet();
-
-// read all keys at once
-Set keys = store.readAllKeySet();
-```
-
## Set
Redis or Valkey based [Set](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RSet.html) object for Java implements [Set](https://docs.oracle.com/javase/8/docs/api/java/util/Set.html) interface. This object is thread-safe. Keeps elements uniqueness via element state comparison. Set size limited to `4 294 967 295` elements. Redis or Valkey uses serialized state to check value uniqueness instead of value's `hashCode()`/`equals()` methods.
diff --git a/docs/data-and-services/objects.md b/docs/data-and-services/objects.md
index 6e4b89a9d..3a091025d 100644
--- a/docs/data-and-services/objects.md
+++ b/docs/data-and-services/objects.md
@@ -290,26 +290,11 @@ set.removeListener(listenerId);
## JSON object holder
Java implementation of [RJsonBucket](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RJsonBucket.html) object stores data in JSON format using `JSON.*` commands. JSON data encoding/decoding handled by `JsonCodec` which is a required parameter. Available implementation is `org.redisson.codec.JacksonCodec` which is thread-safe.
-Use [JSON Store](collections.md/#json-store) for key-value implementation and local cache.
-
-### Local cache
-
-Redisson provides JSON object holder implementation with local cache.
-
-**local cache** - so called near cache used to speed up read operations and avoid network roundtrips. It caches whole JSON object on Redisson side and executes read operations up to **45x faster** in comparison with common implementation. Local cache instances with the same name connected to the same pub/sub channel. This channel is used to exchange invalidate events between instances.
-
-|RedissonClient
method name | Local cache | Ultra-fast
read/write |
-| ------------- | :-----------: | :---------:|
-|getJsonBucket()
open-source version | ❌ | ❌ |
-|getJsonBucket()
[Redisson PRO](https://redisson.pro) version | ❌ | ✔️ |
-|getLocalCachedJsonBucket()
[Redisson PRO](https://redisson.pro) version | ✔️ | ✔️ |
+Use [JSON Store](collections.md/#json-store) for key-value implementation and local cache support.
Code example:
```java
RJsonBucket bucket = redisson.getJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
-// or local cached instance
-RLocalCachedJsonBucket bucket = redisson.getLocalCachedJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
-
bucket.set(new AnyObject(1));
AnyObject obj = bucket.get();
@@ -325,8 +310,6 @@ long aa = bucket.arrayAppend("$.obj.values", "t3", "t4");
Code example of **[Async](https://static.javadoc.io/org.redisson/redisson/latest/org/redisson/api/RJsonBucketAsync.html) interface** usage:
```java
RJsonBucket bucket = redisson.getJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
-// or local cached instace
-RLocalCachedJsonBucket bucket = redisson.getLocalCachedJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
RFuture future = bucket.setAsync(new AnyObject(1));
RFuture objfuture = bucket.getAsync();
@@ -343,9 +326,6 @@ Code example of **[Reactive](https://static.javadoc.io/org.redisson/redisson/lat
```java
RedissonReactiveClient redisson = redissonClient.reactive();
RJsonBucketReactive bucket = redisson.getJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
-// or local cached instance
-RLocalCachedJsonBucketReactive bucket = redisson.getLocalCachedJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
-
Mono mono = bucket.set(new AnyObject(1));
Mono objMono = bucket.get();
@@ -362,8 +342,6 @@ Code example of **[RxJava3](https://static.javadoc.io/org.redisson/redisson/late
```java
RedissonRxClient redisson = redissonClient.rxJava();
RJsonBucketRx bucket = redisson.getJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
-// or local cached instance
-RLocalCachedJsonBucketRx bucket = redisson.getLocalCachedJsonBucket("anyObject", new JacksonCodec<>(AnyObject.class));
Completable rx = bucket.set(new AnyObject(1));
Maybe objRx = bucket.get();
diff --git a/docs/data-and-services/services.md b/docs/data-and-services/services.md
index 1cd628421..582b09d1d 100644
--- a/docs/data-and-services/services.md
+++ b/docs/data-and-services/services.md
@@ -274,11 +274,11 @@ public class MyObject {
}
```
-Please note: fields marked with `transient` keyword aren't stored in Redis.
+Please note: fields marked with `transient` keyword aren't stored in Redis or Valkey.
To start use it you should use one of methods below:
-`RLiveObjectService.attach()` - attaches object to Redis. Discard all the field values already in the detached instance
+`RLiveObjectService.attach()` - attaches object to Redis or Valkey. Discard all the field values already in the detached instance
`RLiveObjectService.merge()` - overrides current object state in Redis or Valkey with the given object state
`RLiveObjectService.persist()` - stores only new object
@@ -288,11 +288,11 @@ Code example:
RLiveObjectService service = redisson.getLiveObjectService();
MyLiveObject myObject = new MyLiveObject();
myObject1.setId("1");
-// current state of myObject is now persisted and attached to Redis
+// current state of myObject is now persisted and attached to Redis or Valkey
myObject = service.persist(myObject);
MyLiveObject myObject = new MyLiveObject("1");
-// current state of myObject is now cleared and attached to Redis
+// current state of myObject is now cleared and attached to Redis or Valkey
myObject = service.attach(myObject);
MyLiveObject myObject = new MyLiveObject();
@@ -335,13 +335,13 @@ List.class | RedissonList.class
The conversion prefers the one nearer to the top of the table if a field type matches more than one entries. i.e. `LinkedList` implements `Deque`, `List`, `Queue`, it will be converted to a `RedissonDeque` because of this.
-Instances of these Redisson classes retains their states/values/entries in Redis or Valkey too, changes to them are directly reflected into Redis or Valkey without keeping values in local VM.
+Instances of these Redisson classes retains their states/values/entries in Redis or Valkey too, changes to them are directly reflected into database without keeping values in local VM.
### Search by Object properties
-Redisson provides comprehensive search engine for Live Object. To make a property participate in search it should be annotated with `@RIndex` annotation.
+Redisson provides comprehensive search engine for RLO objects. To make a property participate in search it should be annotated with `@RIndex` annotation.
-!!! note "Open-source version of search engine is slow"
+!!! note "The open-source version of the search engine is not optimized!"
Use [Redisson PRO](https://redisson.pro) for **ultra-fast search engine**, **low JVM memory consumption during search process** and **search index partitiong in cluster**.
Usage example:
@@ -366,14 +366,14 @@ public class MyObject {
Different type of search conditions are available:
-`Conditions.and` - **AND** condition for collection of nested conditions
-`Conditions.eq` - **EQUALS** condition which restricts property to defined value
-`Conditions.or` - **OR** condition for collection of nested conditions
-`Conditions.in` - **IN** condition which restricts property to set of defined values
-`Conditions.gt` - **GREATER THAN** condition which restricts property to defined value
-`Conditions.ge` - **GREATER THAN ON EQUAL** condition which restricts property to defined value
-`Conditions.lt` - **LESS THAN** condition which restricts property to defined value
-`Conditions.le` - **LESS THAN ON EQUAL** condition which restricts property to defined value
+`Conditions.and()` - **AND** condition for collection of nested conditions
+`Conditions.eq()` - **EQUALS** condition which restricts property to defined value
+`Conditions.or()` - **OR** condition for collection of nested conditions
+`Conditions.in()` - **IN** condition which restricts property to set of defined values
+`Conditions.gt()` - **GREATER THAN** condition which restricts property to defined value
+`Conditions.ge()` - **GREATER THAN ON EQUAL** condition which restricts property to defined value
+`Conditions.lt()` - **LESS THAN** condition which restricts property to defined value
+`Conditions.le()` - **LESS THAN ON EQUAL** condition which restricts property to defined value
Once object stored in Redis or Valkey we can run search:
@@ -392,6 +392,73 @@ Collection objects = liveObjectService.find(MyObject.class,
Search index expires after `expireXXX()` method call only if the Redis or Valkey `notify-keyspace-events` setting contains the letters `Kx`.
+### Local Cache
+
+_This feature is available only in [Redisson PRO](https://redisson.pro) edition._
+
+RLO objects can be cached in local cache on the Redisson side.
+
+**local cache** - so called near cache used to speed up read operations and avoid network roundtrips. It caches JSON Store entries on Redisson side and executes read operations up to **45x faster** in comparison with regular implementation. Local cached instances with the same name are connected to the same pub/sub channel. This channel is used for exchanging of update/invalidate events between all instances. Local cache store doesn't use `hashCode()`/`equals()` methods of key object, instead it uses hash of serialized state.
+
+To make an RLO entity stored in local cache it should be annotated with `@RCache` annotation.
+
+`@RCache` annotation settings:
+
+* `storeCacheMiss` - defines whether to store a cache miss into the local cache. Default value is `false`.
+* `storeMode` - defines store mode of cache data. Default value is `LOCALCACHE_REDIS`. Follow options are available:
+ * `LOCALCACHE` - store data in local cache only and use Redis or Valkey only for data update/invalidation.
+ * `LOCALCACHE_REDIS` - store data in both Redis or Valkey and local cache.
+* `cacheProvider` - defines Cache provider used as local cache store. Default value is `REDISSON`. Follow options are available:
+ * `REDISSON` - uses Redisson own implementation
+ * `CAFFEINE` - uses Caffeine implementation
+* `evictionPolicy` - defines local cache eviction policy. Default value is `NONE`. Follow options are available:
+ * `LFU` - counts how often an item was requested. Those that are used least often are discarded first.
+ * `LRU` - discards the least recently used items first
+ * `SOFT` - uses soft references, entries are removed by GC
+ * `WEAK` - uses weak references, entries are removed by GC
+ * `NONE` - no eviction
+* `cacheSize` - local cache size. If cache size is `0` then local cache is unbounded. If size is `-1` then local cache is always empty and doesn't store data. Default value is `0`.
+* `reconnectionStrategy` - defines strategy for load missed local cache updates after connection failure. Default value is `NONE`. Follow options are available:
+ * `CLEAR` - clear local cache if map instance has been disconnected for a while.
+ * `NONE` - no reconnection handling
+* `syncStrategy` - defines local cache synchronization strategy. Default value is `INVALIDATE`. Follow options are available:
+ * `INVALIDATE` - Default. Invalidate cache entry across all RLocalCachedJsonStore instances on map entry change
+ * `UPDATE` - Insert/update cache entry across all RLocalCachedJsonStore instances on map entry change
+ * `NONE` - No synchronizations on map changes
+* `timeToLive` - defines time to live for each entry in local cache
+* `maxIdle` - defines max idle time for each entry in local cache
+* `useTopicPattern` - defines whether to use a global topic pattern listener that applies to all local cache instances belonging to the same Redisson instance. Default value is `true`.
+
+Usage example:
+
+```java
+@REntity
+@RCache(cacheSize = 10, evictionPolicy = EvictionPolicy.LRU)
+public class MyObject {
+
+ @RId
+ private String id;
+
+ private String name;
+
+ private Integer counter;
+
+}
+
+
+RLiveObjectService service = redisson.getLiveObjectService();
+
+MyObject obj = new MyObject();
+obj.setId("1");
+obj.setName("Simple name");
+
+// current state of myObject is now persisted and attached to Redis or Valkey
+myObject = service.persist(obj);
+
+// loaded from local cache
+String n = myObject.getName();
+```
+
### Advanced Usage
As described before, RLO classes are proxy classes which can be fabricated when needed and then get cached in a `RedissonClient` instance against its original class. This process can be a bit slow and it is recommended to pre-register all the Redisson Live Object classes via `RedissonLiveObjectService` for any kind of delay-sensitive applications. The service can also be used to unregister a class if it is no longer needed. And of course it can be used to check if the class has already been registered.