1818import java .nio .ByteBuffer ;
1919import java .util .concurrent .CompletableFuture ;
2020import java .util .concurrent .atomic .AtomicBoolean ;
21+ import java .util .concurrent .atomic .AtomicInteger ;
2122import java .util .concurrent .atomic .AtomicLong ;
2223import org .reactivestreams .Subscriber ;
2324import org .reactivestreams .Subscription ;
@@ -57,7 +58,7 @@ public class SplittingTransformer<ResponseT, ResultT> implements SdkPublisher<As
5758 /**
5859 * Set to true once {@code .onStream()} is called on the upstreamResponseTransformer
5960 */
60- private final AtomicBoolean onStreamCalled = new AtomicBoolean ( false ) ;
61+ private boolean onStreamCalled ;
6162
6263 /**
6364 * Set to true once {@code .cancel()} is called in the subscription of the downstream subscriber, or if the
@@ -108,16 +109,9 @@ public class SplittingTransformer<ResponseT, ResultT> implements SdkPublisher<As
108109 private volatile CompletableFuture <ResultT > upstreamFuture ;
109110
110111 /**
111- * Tracks whether an {@code IndividualTransformer} has been created for the first part yet. Errors will only be retried for
112- * the first part.
112+ * Tracks the part number. Errors will only be retried for the first part.
113113 */
114- private final AtomicBoolean isFirstIndividualTransformer = new AtomicBoolean (true );
115-
116- /**
117- * Tracks whether an {@code IndividualPartSubscriber} has been created for the first part yet. Errors will only be retried for
118- * the first part.
119- */
120- private final AtomicBoolean isFirstIndividualSubscriber = new AtomicBoolean (true );
114+ private final AtomicInteger partNumber = new AtomicInteger (0 );
121115
122116 private SplittingTransformer (AsyncResponseTransformer <ResponseT , ResultT > upstreamResponseTransformer ,
123117 Long maximumBufferSizeInBytes ,
@@ -206,7 +200,7 @@ private boolean doEmit() {
206200 }
207201 if (outstandingDemand .get () > 0 ) {
208202 demand = outstandingDemand .decrementAndGet ();
209- downstreamSubscriber .onNext (new IndividualTransformer (isFirstIndividualTransformer . compareAndSet ( true , false )));
203+ downstreamSubscriber .onNext (new IndividualTransformer (partNumber . incrementAndGet ( )));
210204 }
211205 }
212206 return false ;
@@ -224,7 +218,7 @@ private void handleSubscriptionCancel() {
224218 log .trace (() -> "downstreamSubscriber already null, skipping downstreamSubscriber.onComplete()" );
225219 return ;
226220 }
227- if (!onStreamCalled . get () ) {
221+ if (!onStreamCalled ) {
228222 // we never subscribe publisherToUpstream to the upstream, it would not complete
229223 downstreamSubscriber = null ;
230224 return ;
@@ -268,19 +262,19 @@ private void handleFutureCancel(Throwable e) {
268262 * body publisher.
269263 */
270264 private class IndividualTransformer implements AsyncResponseTransformer <ResponseT , ResponseT > {
271- private final boolean isFirstPart ;
265+ private final int partNumber ;
272266 private ResponseT response ;
273267 private CompletableFuture <ResponseT > individualFuture ;
274268
275- IndividualTransformer (boolean isFirstPart ) {
276- this .isFirstPart = isFirstPart ;
269+ IndividualTransformer (int partNumber ) {
270+ this .partNumber = partNumber ;
277271 }
278272
279273 @ Override
280274 public CompletableFuture <ResponseT > prepare () {
281275 this .individualFuture = new CompletableFuture <>();
282276
283- if (isFirstPart ) {
277+ if (partNumber == 1 ) {
284278 if (isCancelled .get ()) {
285279 return individualFuture ;
286280 }
@@ -299,7 +293,7 @@ public CompletableFuture<ResponseT> prepare() {
299293
300294 @ Override
301295 public void onResponse (ResponseT response ) {
302- if (isFirstPart ) {
296+ if (partNumber == 1 ) {
303297 log .trace (() -> "calling onResponse on the upstream transformer" );
304298 upstreamResponseTransformer .onResponse (response );
305299 }
@@ -312,8 +306,8 @@ public void onStream(SdkPublisher<ByteBuffer> publisher) {
312306 return ;
313307 }
314308 synchronized (cancelLock ) {
315- if (isFirstPart ) {
316- onStreamCalled . set ( true ) ;
309+ if (partNumber == 1 ) {
310+ onStreamCalled = true ;
317311 log .trace (() -> "calling onStream on the upstream transformer" );
318312 upstreamResponseTransformer .onStream (upstreamSubscriber -> publisherToUpstream .subscribe (
319313 DelegatingBufferingSubscriber .builder ()
@@ -324,22 +318,25 @@ public void onStream(SdkPublisher<ByteBuffer> publisher) {
324318 }
325319 }
326320
327- if (!resultFuture .isDone ()) {
328- CompletableFutureUtils .forwardResultTo (upstreamFuture , resultFuture );
329- }
330-
331- publisher .subscribe (new IndividualPartSubscriber <>(this .individualFuture , response ,
332- isFirstIndividualSubscriber .compareAndSet (true , false )));
321+ CompletableFutureUtils .forwardResultTo (upstreamFuture , resultFuture );
322+ publisher .subscribe (new IndividualPartSubscriber <>(this .individualFuture , response , partNumber ));
333323 }
334324
335325 @ Override
336326 public void exceptionOccurred (Throwable error ) {
337327 log .trace (() -> "calling exceptionOccurred on the upstream transformer" );
338- upstreamResponseTransformer .exceptionOccurred (error );
339328
340- if (! isFirstPart || onStreamCalled . get () ) {
341- publisherToUpstream . error (error );
329+ if (partNumber == 1 ) {
330+ upstreamResponseTransformer . exceptionOccurred (error );
342331 }
332+
333+ // TODO - add comments explaining
334+ synchronized (cancelLock ) {
335+ if (partNumber > 1 || onStreamCalled ) {
336+ publisherToUpstream .error (error );
337+ }
338+ }
339+
343340 }
344341 }
345342
@@ -350,13 +347,13 @@ class IndividualPartSubscriber<T> implements Subscriber<ByteBuffer> {
350347
351348 private final CompletableFuture <T > future ;
352349 private final T response ;
353- private final boolean isFirstPart ;
350+ private final int partNumber ;
354351 private Subscription subscription ;
355352
356- IndividualPartSubscriber (CompletableFuture <T > future , T response , boolean isFirstPart ) {
353+ IndividualPartSubscriber (CompletableFuture <T > future , T response , int partNumber ) {
357354 this .future = future ;
358355 this .response = response ;
359- this .isFirstPart = isFirstPart ;
356+ this .partNumber = partNumber ;
360357 }
361358
362359 @ Override
@@ -396,7 +393,7 @@ public void onComplete() {
396393 }
397394
398395 private void handleError (Throwable t ) {
399- if (! isFirstPart ) {
396+ if (partNumber > 1 ) {
400397 publisherToUpstream .error (t );
401398 }
402399 future .completeExceptionally (t );
0 commit comments