24
24
import org .springframework .util .Assert ;
25
25
26
26
/**
27
- * {@link RedisCacheWriter} provides low-level access to Redis commands ({@code SET, SETNX, GET, EXPIRE,...})
28
- * used for caching.
27
+ * {@link RedisCacheWriter} provides low-level access to Redis commands ({@code SET, SETNX, GET, EXPIRE,...}) used for
28
+ * caching.
29
29
* <p>
30
30
* The {@link RedisCacheWriter} may be shared by multiple cache implementations and is responsible for reading/writing
31
31
* binary data from/to Redis. The implementation honors potential cache lock flags that might be set.
32
32
* <p>
33
- * The default {@link RedisCacheWriter} implementation can be customized with {@link BatchStrategy}
34
- * to tune performance behavior.
33
+ * The default {@link RedisCacheWriter} implementation can be customized with {@link BatchStrategy} to tune performance
34
+ * behavior.
35
35
*
36
36
* @author Christoph Strobl
37
37
* @author Mark Paluch
@@ -96,9 +96,8 @@ static RedisCacheWriter lockingRedisCacheWriter(RedisConnectionFactory connectio
96
96
*
97
97
* @param connectionFactory must not be {@literal null}.
98
98
* @param sleepTime sleep time between lock access attempts, must not be {@literal null}.
99
- * @param lockTtlFunction TTL function to compute the Lock TTL. The function is called with contextual keys
100
- * and values (such as the cache name on cleanup or the actual key/value on put requests);
101
- * must not be {@literal null}.
99
+ * @param lockTtlFunction TTL function to compute the Lock TTL. The function is called with contextual keys and values
100
+ * (such as the cache name on cleanup or the actual key/value on put requests); must not be {@literal null}.
102
101
* @param batchStrategy must not be {@literal null}.
103
102
* @return new instance of {@link DefaultRedisCacheWriter}.
104
103
* @since 3.2
@@ -124,8 +123,8 @@ static RedisCacheWriter lockingRedisCacheWriter(RedisConnectionFactory connectio
124
123
byte [] get (String name , byte [] key );
125
124
126
125
/**
127
- * Get the binary value representation from Redis stored for the given key and set
128
- * the given {@link Duration TTL expiration} for the cache entry.
126
+ * Get the binary value representation from Redis stored for the given key and set the given {@link Duration TTL
127
+ * expiration} for the cache entry.
129
128
*
130
129
* @param name must not be {@literal null}.
131
130
* @param key must not be {@literal null}.
@@ -138,14 +137,41 @@ default byte[] get(String name, byte[] key, @Nullable Duration ttl) {
138
137
}
139
138
140
139
/**
141
- * Determines whether the asynchronous {@link #retrieve(String, byte[])}
142
- * and {@link #retrieve(String, byte[], Duration)} cache operations are supported by the implementation .
140
+ * Get the binary value representation from Redis stored for the given key and set the given {@link Duration TTL
141
+ * expiration} for the cache entry, obtaining the value from {@code valueLoader} if necessary .
143
142
* <p>
144
- * The main factor for whether the {@literal retrieve} operation can be supported will primarily be determined
145
- * by the Redis driver in use at runtime.
143
+ * If possible (and configured for locking), implementations should ensure that the loading operation is synchronized
144
+ * so that the specified {@code valueLoader} is only called once in case of concurrent access on the same key.
145
+ *
146
+ * @param name must not be {@literal null}.
147
+ * @param key must not be {@literal null}.
148
+ * @param valueLoader value loader that creates the value if the cache lookup has been not successful.
149
+ * @param ttl {@link Duration} specifying the {@literal expiration timeout} for the cache entry.
150
+ * @param timeToIdleEnabled {@literal true} to enable Time to Idle when retrieving the value.
151
+ * @since 3.4
152
+ */
153
+ default byte [] get (String name , byte [] key , Supplier <byte []> valueLoader , @ Nullable Duration ttl ,
154
+ boolean timeToIdleEnabled ) {
155
+
156
+ byte [] bytes = timeToIdleEnabled ? get (name , key , ttl ) : get (name , key );
157
+
158
+ if (bytes == null ) {
159
+ bytes = valueLoader .get ();
160
+ put (name , key , bytes , ttl );
161
+ }
162
+
163
+ return bytes ;
164
+ }
165
+
166
+ /**
167
+ * Determines whether the asynchronous {@link #retrieve(String, byte[])} and
168
+ * {@link #retrieve(String, byte[], Duration)} cache operations are supported by the implementation.
169
+ * <p>
170
+ * The main factor for whether the {@literal retrieve} operation can be supported will primarily be determined by the
171
+ * Redis driver in use at runtime.
146
172
* <p>
147
- * Returns {@literal false} by default. This will have an effect of {@link RedisCache#retrieve(Object)}
148
- * and {@link RedisCache#retrieve(Object, Supplier)} throwing an {@link UnsupportedOperationException}.
173
+ * Returns {@literal false} by default. This will have an effect of {@link RedisCache#retrieve(Object)} and
174
+ * {@link RedisCache#retrieve(Object, Supplier)} throwing an {@link UnsupportedOperationException}.
149
175
*
150
176
* @return {@literal true} if asynchronous {@literal retrieve} operations are supported by the implementation.
151
177
* @since 3.2
@@ -155,8 +181,8 @@ default boolean supportsAsyncRetrieve() {
155
181
}
156
182
157
183
/**
158
- * Asynchronously retrieves the {@link CompletableFuture value} to which the {@link RedisCache}
159
- * maps the given {@link byte[] key}.
184
+ * Asynchronously retrieves the {@link CompletableFuture value} to which the {@link RedisCache} maps the given
185
+ * {@link byte[] key}.
160
186
* <p>
161
187
* This operation is non-blocking.
162
188
*
@@ -171,8 +197,8 @@ default CompletableFuture<byte[]> retrieve(String name, byte[] key) {
171
197
}
172
198
173
199
/**
174
- * Asynchronously retrieves the {@link CompletableFuture value} to which the {@link RedisCache} maps
175
- * the given {@link byte[] key} setting the {@link Duration TTL expiration} for the cache entry.
200
+ * Asynchronously retrieves the {@link CompletableFuture value} to which the {@link RedisCache} maps the given
201
+ * {@link byte[] key} setting the {@link Duration TTL expiration} for the cache entry.
176
202
* <p>
177
203
* This operation is non-blocking.
178
204
*
@@ -264,8 +290,8 @@ interface TtlFunction {
264
290
/**
265
291
* Creates a {@literal Singleton} {@link TtlFunction} using the given {@link Duration}.
266
292
*
267
- * @param duration the time to live. Can be {@link Duration#ZERO} for persistent values (i.e. cache entry
268
- * does not expire).
293
+ * @param duration the time to live. Can be {@link Duration#ZERO} for persistent values (i.e. cache entry does not
294
+ * expire).
269
295
* @return a singleton {@link TtlFunction} using {@link Duration}.
270
296
*/
271
297
static TtlFunction just (Duration duration ) {
0 commit comments