|
22 | 22 | import java.util.concurrent.atomic.AtomicBoolean;
|
23 | 23 | import java.util.concurrent.atomic.AtomicReference;
|
24 | 24 | import java.util.concurrent.atomic.LongAdder;
|
| 25 | +import java.util.concurrent.locks.LockSupport; |
25 | 26 | import java.util.function.Function;
|
26 | 27 | import java.util.logging.Level;
|
27 | 28 | import java.util.stream.Stream;
|
|
33 | 34 | import org.mockito.Mockito;
|
34 | 35 | import org.reactivestreams.Publisher;
|
35 | 36 | import org.reactivestreams.Subscription;
|
36 |
| - |
37 | 37 | import reactor.core.CoreSubscriber;
|
38 | 38 | import reactor.core.Disposable;
|
39 | 39 | import reactor.core.Fuseable;
|
40 | 40 | import reactor.core.Scannable.Attr;
|
41 | 41 | import reactor.core.TestLoggerExtension;
|
42 | 42 | import reactor.core.publisher.FluxUsingWhen.ResourceSubscriber;
|
43 | 43 | import reactor.core.publisher.FluxUsingWhen.UsingWhenSubscriber;
|
| 44 | +import reactor.core.scheduler.Schedulers; |
44 | 45 | import reactor.test.ParameterizedTestWithName;
|
45 | 46 | import reactor.test.StepVerifier;
|
46 | 47 | import reactor.test.publisher.PublisherProbe;
|
47 | 48 | import reactor.test.publisher.TestPublisher;
|
48 | 49 | import reactor.test.util.TestLogger;
|
49 |
| -import reactor.util.Loggers; |
50 | 50 | import reactor.util.annotation.Nullable;
|
51 | 51 | import reactor.util.context.Context;
|
52 | 52 | import reactor.util.function.Tuple2;
|
@@ -705,6 +705,43 @@ public void apiCancel(Flux<String> transactionToCancel) {
|
705 | 705 | .matches(tr -> tr.cancelProbe.wasSubscribed(), "cancel method used");
|
706 | 706 | }
|
707 | 707 |
|
| 708 | + @ParameterizedTestWithName |
| 709 | + @MethodSource("sourcesFullTransaction") |
| 710 | + public void lateResourcePublisherCleanupIsDeferredOnCancel(Flux<String> transactionToCancel) |
| 711 | + throws InterruptedException { |
| 712 | + AtomicReference<TestResource> ref = new AtomicReference<>(); |
| 713 | + CountDownLatch resourceSubscribeLatch = new CountDownLatch(1); |
| 714 | + CountDownLatch resourceCancelLatch = new CountDownLatch(1); |
| 715 | + Flux<String> flux = Flux.usingWhen(Mono.fromCallable(() -> { |
| 716 | + LockSupport.parkNanos(Duration.ofMillis(100).toNanos()); |
| 717 | + TestResource testResource = new TestResource(); |
| 718 | + ref.set(testResource); |
| 719 | + resourceSubscribeLatch.countDown(); |
| 720 | + return testResource; |
| 721 | + }).subscribeOn(Schedulers.single()), |
| 722 | + d -> transactionToCancel, |
| 723 | + TestResource::commit, |
| 724 | + TestResource::rollback, |
| 725 | + testResource -> testResource.cancel() |
| 726 | + .doOnSubscribe(unused -> resourceCancelLatch.countDown())); |
| 727 | + |
| 728 | + StepVerifier.create(flux.take(Duration.ofMillis(10)), 1) |
| 729 | + .verifyComplete(); |
| 730 | + |
| 731 | + assertThat(resourceSubscribeLatch.await(1, TimeUnit.SECONDS)) |
| 732 | + .as("Resource create subscribed") |
| 733 | + .isTrue(); |
| 734 | + assertThat(resourceCancelLatch.await(1, TimeUnit.SECONDS)) |
| 735 | + .as("Resource cancel subscribed") |
| 736 | + .isTrue(); |
| 737 | + |
| 738 | + assertThat(ref.get()) |
| 739 | + .isNotNull() |
| 740 | + .matches(tr -> !tr.commitProbe.wasSubscribed(), "no commit") |
| 741 | + .matches(tr -> !tr.rollbackProbe.wasSubscribed(), "no rollback") |
| 742 | + .matches(tr -> tr.cancelProbe.wasSubscribed(), "cancel method used"); |
| 743 | + } |
| 744 | + |
708 | 745 | @ParameterizedTestWithName
|
709 | 746 | @MethodSource("sourcesFullTransaction")
|
710 | 747 | @TestLoggerExtension.Redirect
|
|
0 commit comments