17
17
18
18
package io .helidon .common .reactive ;
19
19
20
+ import java .util .LinkedList ;
20
21
import java .util .Objects ;
21
22
import java .util .Optional ;
23
+ import java .util .Queue ;
22
24
import java .util .concurrent .Flow ;
23
25
import java .util .concurrent .atomic .AtomicBoolean ;
24
26
@@ -50,6 +52,7 @@ public class MultiCoupledProcessor<T, R> implements Flow.Processor<T, R>, Multi<
50
52
private Flow .Subscription inletSubscription ;
51
53
private Flow .Subscription passedInPublisherSubscription ;
52
54
private AtomicBoolean cancelled = new AtomicBoolean (false );
55
+ private Queue <Runnable > forbiddenCalls = new LinkedList <>();
53
56
54
57
private MultiCoupledProcessor (Flow .Subscriber <T > passedInSubscriber , Flow .Publisher <R > passedInPublisher ) {
55
58
this .passedInSubscriber = SequentialSubscriber .create (passedInSubscriber );
@@ -78,7 +81,7 @@ public void subscribe(Flow.Subscriber<? super R> outletSubscriber) {
78
81
79
82
@ Override
80
83
public void onSubscribe (Flow .Subscription passedInPublisherSubscription ) {
81
- //Passed in publisher called onSubscribed
84
+ //Passed in publisher called onSubscribe
82
85
Objects .requireNonNull (passedInPublisherSubscription );
83
86
// https://github.com/reactive-streams/reactive-streams-jvm#2.5
84
87
if (Objects .nonNull (MultiCoupledProcessor .this .passedInPublisherSubscription ) || cancelled .get ()) {
@@ -91,6 +94,7 @@ public void onSubscribe(Flow.Subscription passedInPublisherSubscription) {
91
94
@ Override
92
95
@ SuppressWarnings ("unchecked" )
93
96
public void onNext (R t ) {
97
+ tryForbiddenCalls ();
94
98
//Passed in publisher sent onNext
95
99
Objects .requireNonNull (t );
96
100
outletSubscriber .onNext (t );
@@ -105,7 +109,7 @@ public void onError(Throwable t) {
105
109
passedInSubscriber .onError (t );
106
110
inletSubscriber .onError (t );
107
111
//203 https://github.com/eclipse/microprofile-reactive-streams-operators/issues/131
108
- Optional .ofNullable (inletSubscription ).ifPresent (Flow .Subscription ::cancel );
112
+ forbiddenCalls . offer (() -> Optional .ofNullable (inletSubscription ).ifPresent (Flow .Subscription ::cancel ) );
109
113
}
110
114
111
115
@ Override
@@ -115,7 +119,7 @@ public void onComplete() {
115
119
outletSubscriber .onComplete ();
116
120
passedInSubscriber .onComplete ();
117
121
//203 https://github.com/eclipse/microprofile-reactive-streams-operators/issues/131
118
- Optional .ofNullable (inletSubscription ).ifPresent (Flow .Subscription ::cancel );
122
+ forbiddenCalls . offer (() -> Optional .ofNullable (inletSubscription ).ifPresent (Flow .Subscription ::cancel ) );
119
123
}
120
124
});
121
125
@@ -124,11 +128,8 @@ public void onComplete() {
124
128
@ Override
125
129
public void request (long n ) {
126
130
// Request from outlet subscriber
127
- StreamValidationUtils .checkRecursionDepth (
128
- "MultiCoupledProcessor1" ,
129
- 8 ,
130
- () -> passedInPublisherSubscription .request (n ),
131
- (actDepth , t ) -> outletSubscriber .onError (t ));
131
+ passedInPublisherSubscription .request (n );
132
+ tryForbiddenCalls ();
132
133
}
133
134
134
135
@ Override
@@ -137,6 +138,7 @@ public void cancel() {
137
138
passedInSubscriber .onComplete ();
138
139
Optional .ofNullable (inletSubscription ).ifPresent (Flow .Subscription ::cancel );
139
140
passedInPublisherSubscription .cancel ();
141
+ tryForbiddenCalls ();
140
142
}
141
143
});
142
144
}
@@ -153,11 +155,8 @@ public void onSubscribe(Flow.Subscription inletSubscription) {
153
155
passedInSubscriber .onSubscribe (new Flow .Subscription () {
154
156
@ Override
155
157
public void request (long n ) {
156
- StreamValidationUtils .checkRecursionDepth (
157
- "MultiCoupledProcessor2" ,
158
- 8 ,
159
- () -> inletSubscription .request (n ),
160
- (actDepth , t ) -> passedInSubscriber .onError (t ));
158
+ inletSubscription .request (n );
159
+ tryForbiddenCalls ();
161
160
}
162
161
163
162
@ Override
@@ -169,6 +168,7 @@ public void cancel() {
169
168
inletSubscription .cancel ();
170
169
outletSubscriber .onComplete ();
171
170
passedInPublisherSubscription .cancel ();
171
+ tryForbiddenCalls ();
172
172
}
173
173
});
174
174
}
@@ -197,4 +197,14 @@ public void onComplete() {
197
197
passedInPublisherSubscription .cancel ();
198
198
}
199
199
200
+ private void tryForbiddenCalls () {
201
+ while (true ) {
202
+ Runnable polledCall = forbiddenCalls .poll ();
203
+ if (Objects .isNull (polledCall )) {
204
+ return ;
205
+ }
206
+ polledCall .run ();
207
+ }
208
+ }
209
+
200
210
}
0 commit comments