|
26 | 26 | import java.util.Optional;
|
27 | 27 | import java.util.concurrent.CompletableFuture;
|
28 | 28 | import java.util.concurrent.ConcurrentHashMap;
|
29 |
| -import java.util.concurrent.atomic.AtomicReference; |
30 | 29 | import java.util.function.Supplier;
|
31 | 30 |
|
32 | 31 | import org.apache.commons.logging.Log;
|
33 | 32 | import org.apache.commons.logging.LogFactory;
|
34 |
| -import reactor.core.observability.DefaultSignalListener; |
| 33 | +import org.reactivestreams.Subscriber; |
| 34 | +import org.reactivestreams.Subscription; |
35 | 35 | import reactor.core.publisher.Flux;
|
36 | 36 | import reactor.core.publisher.Mono;
|
37 | 37 |
|
|
90 | 90 | * @author Sam Brannen
|
91 | 91 | * @author Stephane Nicoll
|
92 | 92 | * @author Sebastien Deleuze
|
93 |
| - * @author Simon Baslé |
94 | 93 | * @since 3.1
|
95 | 94 | */
|
96 | 95 | public abstract class CacheAspectSupport extends AbstractCacheInvoker
|
@@ -1037,45 +1036,34 @@ public void performCachePut(@Nullable Object value) {
|
1037 | 1036 |
|
1038 | 1037 |
|
1039 | 1038 | /**
|
1040 |
| - * Reactor stateful SignalListener for collecting a List to cache. |
| 1039 | + * Reactive Streams Subscriber for exhausting the Flux and collecting a List |
| 1040 | + * to cache. |
1041 | 1041 | */
|
1042 |
| - private class CachePutSignalListener extends DefaultSignalListener<Object> { |
| 1042 | + private final class CachePutListSubscriber implements Subscriber<Object> { |
1043 | 1043 |
|
1044 |
| - private final AtomicReference<CachePutRequest> request; |
| 1044 | + private final CachePutRequest request; |
1045 | 1045 |
|
1046 | 1046 | private final List<Object> cacheValue = new ArrayList<>();
|
1047 | 1047 |
|
1048 |
| - public CachePutSignalListener(CachePutRequest request) { |
1049 |
| - this.request = new AtomicReference<>(request); |
| 1048 | + public CachePutListSubscriber(CachePutRequest request) { |
| 1049 | + this.request = request; |
1050 | 1050 | }
|
1051 | 1051 |
|
1052 | 1052 | @Override
|
1053 |
| - public void doOnNext(Object o) { |
1054 |
| - this.cacheValue.add(o); |
| 1053 | + public void onSubscribe(Subscription s) { |
| 1054 | + s.request(Integer.MAX_VALUE); |
1055 | 1055 | }
|
1056 |
| - |
1057 | 1056 | @Override
|
1058 |
| - public void doOnComplete() { |
1059 |
| - CachePutRequest r = this.request.get(); |
1060 |
| - if (this.request.compareAndSet(r, null)) { |
1061 |
| - r.performCachePut(this.cacheValue); |
1062 |
| - } |
| 1057 | + public void onNext(Object o) { |
| 1058 | + this.cacheValue.add(o); |
1063 | 1059 | }
|
1064 |
| - |
1065 | 1060 | @Override
|
1066 |
| - public void doOnCancel() { |
1067 |
| - // Note: we don't use doFinally as we want to propagate the signal after cache put, not before |
1068 |
| - CachePutRequest r = this.request.get(); |
1069 |
| - if (this.request.compareAndSet(r, null)) { |
1070 |
| - r.performCachePut(this.cacheValue); |
1071 |
| - } |
| 1061 | + public void onError(Throwable t) { |
| 1062 | + this.cacheValue.clear(); |
1072 | 1063 | }
|
1073 |
| - |
1074 | 1064 | @Override
|
1075 |
| - public void doOnError(Throwable error) { |
1076 |
| - if (this.request.getAndSet(null) != null) { |
1077 |
| - this.cacheValue.clear(); |
1078 |
| - } |
| 1065 | + public void onComplete() { |
| 1066 | + this.request.performCachePut(this.cacheValue); |
1079 | 1067 | }
|
1080 | 1068 | }
|
1081 | 1069 |
|
@@ -1159,8 +1147,10 @@ public Object processPutRequest(CachePutRequest request, @Nullable Object result
|
1159 | 1147 | ReactiveAdapter adapter = (result != null ? this.registry.getAdapter(result.getClass()) : null);
|
1160 | 1148 | if (adapter != null) {
|
1161 | 1149 | if (adapter.isMultiValue()) {
|
1162 |
| - return adapter.fromPublisher(Flux.from(adapter.toPublisher(result)) |
1163 |
| - .tap(() -> new CachePutSignalListener(request))); |
| 1150 | + Flux<?> source = Flux.from(adapter.toPublisher(result)) |
| 1151 | + .publish().refCount(2); |
| 1152 | + source.subscribe(new CachePutListSubscriber(request)); |
| 1153 | + return adapter.fromPublisher(source); |
1164 | 1154 | }
|
1165 | 1155 | else {
|
1166 | 1156 | return adapter.fromPublisher(Mono.from(adapter.toPublisher(result))
|
|
0 commit comments