|
15 | 15 | */
|
16 | 16 | package org.springframework.data.redis.cache;
|
17 | 17 |
|
18 |
| -import java.util.ArrayList; |
19 |
| -import java.util.Collections; |
20 |
| -import java.util.Iterator; |
21 |
| -import java.util.List; |
22 |
| -import java.util.NoSuchElementException; |
23 |
| -import java.util.Optional; |
24 |
| - |
25 | 18 | import org.springframework.data.redis.connection.RedisConnection;
|
26 |
| -import org.springframework.data.redis.core.Cursor; |
27 |
| -import org.springframework.data.redis.core.ScanOptions; |
28 |
| -import org.springframework.util.Assert; |
29 | 19 |
|
30 | 20 | /**
|
31 |
| - * Batch strategies to be used with {@link RedisCacheWriter}. |
| 21 | + * A {@link BatchStrategy} to be used with {@link RedisCacheWriter}. |
| 22 | + * <p/> |
| 23 | + * Mainly used to clear the cache. |
32 | 24 | * <p/>
|
33 |
| - * Primarily used to clear the cache. |
| 25 | + * Predefined strategies using the {@link BatchStrategies#keys() KEYS} or {@link BatchStrategies#scan(int) SCAN} |
| 26 | + * commands can be found in {@link BatchStrategies}. |
34 | 27 | *
|
35 | 28 | * @author Mark Paluch
|
| 29 | + * @author Christoph Strobl |
36 | 30 | * @since 2.6
|
37 | 31 | */
|
38 |
| -public abstract class BatchStrategy { |
39 |
| - |
40 |
| - /** |
41 |
| - * Batching strategy using a single {@code KEYS} and {@code DEL} command to remove all matching keys. {@code KEYS} |
42 |
| - * scans the entire keyspace of the Redis database and can block the Redis worker thread for a long time on large |
43 |
| - * keyspaces. |
44 |
| - * <p/> |
45 |
| - * {@code KEYS} is supported for standalone and clustered (sharded) Redis operation modes. |
46 |
| - * |
47 |
| - * @return batching strategy using {@code KEYS}. |
48 |
| - */ |
49 |
| - public static BatchStrategy keys() { |
50 |
| - return Keys.INSTANCE; |
51 |
| - } |
52 |
| - |
53 |
| - /** |
54 |
| - * Batching strategy using a {@code SCAN} cursors and potentially multiple {@code DEL} commands to remove all matching |
55 |
| - * keys. This strategy allows a configurable batch size to optimize for scan batching. |
56 |
| - * <p/> |
57 |
| - * Note that using the {@code SCAN} strategy might be not supported on all drivers and Redis operation modes. |
58 |
| - * |
59 |
| - * @return batching strategy using {@code SCAN}. |
60 |
| - */ |
61 |
| - public static BatchStrategy scan(int batchSize) { |
62 |
| - |
63 |
| - Assert.isTrue(batchSize > 0, "Batch size must be greater than zero"); |
64 |
| - |
65 |
| - return new Scan(batchSize); |
66 |
| - } |
| 32 | +public interface BatchStrategy { |
67 | 33 |
|
68 | 34 | /**
|
69 | 35 | * Remove all keys following the given pattern.
|
70 | 36 | *
|
71 |
| - * @param the connection to use. |
72 |
| - * @param name The cache name must not be {@literal null}. |
| 37 | + * @param connection the connection to use. Must not be {@literal null}. |
| 38 | + * @param name The cache name. Must not be {@literal null}. |
73 | 39 | * @param pattern The pattern for the keys to remove. Must not be {@literal null}.
|
74 | 40 | * @return number of removed keys.
|
75 | 41 | */
|
76 |
| - abstract int cleanCache(RedisConnection connection, String name, byte[] pattern); |
77 |
| - |
78 |
| - /** |
79 |
| - * {@link BatchStrategy} using {@code KEYS}. |
80 |
| - */ |
81 |
| - static class Keys extends BatchStrategy { |
82 |
| - |
83 |
| - static Keys INSTANCE = new Keys(); |
84 |
| - |
85 |
| - @Override |
86 |
| - int cleanCache(RedisConnection connection, String name, byte[] pattern) { |
87 |
| - |
88 |
| - byte[][] keys = Optional.ofNullable(connection.keys(pattern)).orElse(Collections.emptySet()) |
89 |
| - .toArray(new byte[0][]); |
90 |
| - |
91 |
| - if (keys.length > 0) { |
92 |
| - connection.del(keys); |
93 |
| - } |
94 |
| - |
95 |
| - return keys.length; |
96 |
| - } |
97 |
| - } |
98 |
| - |
99 |
| - /** |
100 |
| - * {@link BatchStrategy} using {@code SCAN}. |
101 |
| - */ |
102 |
| - static class Scan extends BatchStrategy { |
103 |
| - |
104 |
| - private final int batchSize; |
105 |
| - |
106 |
| - public Scan(int batchSize) { |
107 |
| - this.batchSize = batchSize; |
108 |
| - } |
109 |
| - |
110 |
| - @Override |
111 |
| - int cleanCache(RedisConnection connection, String name, byte[] pattern) { |
112 |
| - |
113 |
| - Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().count(batchSize).match(pattern).build()); |
114 |
| - |
115 |
| - PartitionIterator<byte[]> partitions = new PartitionIterator<>(cursor, batchSize); |
116 |
| - |
117 |
| - int count = 0; |
118 |
| - |
119 |
| - while (partitions.hasNext()) { |
120 |
| - |
121 |
| - List<byte[]> keys = partitions.next(); |
122 |
| - count += keys.size(); |
123 |
| - |
124 |
| - if (keys.size() > 0) { |
125 |
| - connection.del(keys.toArray(new byte[0][])); |
126 |
| - } |
127 |
| - } |
128 |
| - |
129 |
| - return count; |
130 |
| - } |
131 |
| - } |
132 |
| - |
133 |
| - /** |
134 |
| - * Utility to split and buffer outcome from a {@link Iterator} into {@link List lists} of {@code T} with a maximum |
135 |
| - * chunks {@code size}. |
136 |
| - * |
137 |
| - * @param <T> |
138 |
| - */ |
139 |
| - static class PartitionIterator<T> implements Iterator<List<T>> { |
140 |
| - |
141 |
| - private final Iterator<T> iterator; |
142 |
| - private final int size; |
143 |
| - |
144 |
| - public PartitionIterator(Iterator<T> iterator, int size) { |
145 |
| - this.iterator = iterator; |
146 |
| - this.size = size; |
147 |
| - } |
148 |
| - |
149 |
| - @Override |
150 |
| - public boolean hasNext() { |
151 |
| - return iterator.hasNext(); |
152 |
| - } |
153 |
| - |
154 |
| - @Override |
155 |
| - public List<T> next() { |
156 |
| - |
157 |
| - if (!hasNext()) { |
158 |
| - throw new NoSuchElementException(); |
159 |
| - } |
160 |
| - |
161 |
| - List<T> list = new ArrayList<>(size); |
162 |
| - while (list.size() < size && iterator.hasNext()) { |
163 |
| - list.add(iterator.next()); |
164 |
| - } |
165 |
| - |
166 |
| - return list; |
167 |
| - } |
168 |
| - } |
| 42 | + long cleanCache(RedisConnection connection, String name, byte[] pattern); |
169 | 43 |
|
170 | 44 | }
|
0 commit comments