32
32
import java .util .concurrent .atomic .AtomicBoolean ;
33
33
import java .util .concurrent .atomic .AtomicLong ;
34
34
import java .util .function .Consumer ;
35
+ import java .util .function .IntPredicate ;
35
36
36
37
import org .reactivestreams .Publisher ;
37
38
import org .reactivestreams .Subscription ;
@@ -473,6 +474,9 @@ public static Consumer<DataBuffer> releaseConsumer() {
473
474
* Depending on the {@link DataBuffer} implementation, the returned buffer may be a single
474
475
* buffer containing all data of the provided buffers, or it may be a true composite that
475
476
* contains references to the buffers.
477
+ * <p>If {@code dataBuffers} contains an error signal, then all buffers that preceded the error
478
+ * will be {@linkplain #release(DataBuffer) released}, and the error is stored in the
479
+ * returned {@code Mono}.
476
480
* @param dataBuffers the data buffers that are to be composed
477
481
* @return a buffer that is composed from the {@code dataBuffers} argument
478
482
* @since 5.0.3
@@ -481,14 +485,26 @@ public static Mono<DataBuffer> join(Publisher<DataBuffer> dataBuffers) {
481
485
Assert .notNull (dataBuffers , "'dataBuffers' must not be null" );
482
486
483
487
return Flux .from (dataBuffers )
488
+ .onErrorResume (DataBufferUtils ::exceptionDataBuffer )
484
489
.collectList ()
485
490
.filter (list -> !list .isEmpty ())
486
- .map (list -> {
491
+ .flatMap (list -> {
492
+ for (int i = 0 ; i < list .size (); i ++) {
493
+ DataBuffer dataBuffer = list .get (i );
494
+ if (dataBuffer instanceof ExceptionDataBuffer ) {
495
+ list .subList (0 , i ).forEach (DataBufferUtils ::release );
496
+ return Mono .error (((ExceptionDataBuffer ) dataBuffer ).throwable ());
497
+ }
498
+ }
487
499
DataBufferFactory bufferFactory = list .get (0 ).factory ();
488
- return bufferFactory .join (list );
500
+ return Mono . just ( bufferFactory .join (list ) );
489
501
});
490
502
}
491
503
504
+ private static Mono <DataBuffer > exceptionDataBuffer (Throwable throwable ) {
505
+ return Mono .just (new ExceptionDataBuffer (throwable ));
506
+ }
507
+
492
508
493
509
private static class ReadableByteChannelGenerator implements Consumer <SynchronousSink <DataBuffer >> {
494
510
@@ -658,4 +674,154 @@ public void failed(Throwable exc, ByteBuffer byteBuffer) {
658
674
}
659
675
}
660
676
677
+
678
+ /**
679
+ * DataBuffer implementation that holds a {@link Throwable}, used in {@link #join(Publisher)}.
680
+ */
681
+ private static final class ExceptionDataBuffer implements DataBuffer {
682
+
683
+ private final Throwable throwable ;
684
+
685
+
686
+ public ExceptionDataBuffer (Throwable throwable ) {
687
+ this .throwable = throwable ;
688
+ }
689
+
690
+ public Throwable throwable () {
691
+ return this .throwable ;
692
+ }
693
+
694
+ // Unsupported
695
+
696
+ @ Override
697
+ public DataBufferFactory factory () {
698
+ throw new UnsupportedOperationException ();
699
+ }
700
+
701
+ @ Override
702
+ public int indexOf (IntPredicate predicate , int fromIndex ) {
703
+ throw new UnsupportedOperationException ();
704
+ }
705
+
706
+ @ Override
707
+ public int lastIndexOf (IntPredicate predicate , int fromIndex ) {
708
+ throw new UnsupportedOperationException ();
709
+ }
710
+
711
+ @ Override
712
+ public int readableByteCount () {
713
+ throw new UnsupportedOperationException ();
714
+ }
715
+
716
+ @ Override
717
+ public int writableByteCount () {
718
+ throw new UnsupportedOperationException ();
719
+ }
720
+
721
+ @ Override
722
+ public int capacity () {
723
+ throw new UnsupportedOperationException ();
724
+ }
725
+
726
+ @ Override
727
+ public DataBuffer capacity (int capacity ) {
728
+ throw new UnsupportedOperationException ();
729
+ }
730
+
731
+ @ Override
732
+ public int readPosition () {
733
+ throw new UnsupportedOperationException ();
734
+ }
735
+
736
+ @ Override
737
+ public DataBuffer readPosition (int readPosition ) {
738
+ throw new UnsupportedOperationException ();
739
+ }
740
+
741
+ @ Override
742
+ public int writePosition () {
743
+ throw new UnsupportedOperationException ();
744
+ }
745
+
746
+ @ Override
747
+ public DataBuffer writePosition (int writePosition ) {
748
+ throw new UnsupportedOperationException ();
749
+ }
750
+
751
+ @ Override
752
+ public byte getByte (int index ) {
753
+ throw new UnsupportedOperationException ();
754
+ }
755
+
756
+ @ Override
757
+ public byte read () {
758
+ throw new UnsupportedOperationException ();
759
+ }
760
+
761
+ @ Override
762
+ public DataBuffer read (byte [] destination ) {
763
+ throw new UnsupportedOperationException ();
764
+ }
765
+
766
+ @ Override
767
+ public DataBuffer read (byte [] destination , int offset , int length ) {
768
+ throw new UnsupportedOperationException ();
769
+ }
770
+
771
+ @ Override
772
+ public DataBuffer write (byte b ) {
773
+ throw new UnsupportedOperationException ();
774
+ }
775
+
776
+ @ Override
777
+ public DataBuffer write (byte [] source ) {
778
+ throw new UnsupportedOperationException ();
779
+ }
780
+
781
+ @ Override
782
+ public DataBuffer write (byte [] source , int offset , int length ) {
783
+ throw new UnsupportedOperationException ();
784
+ }
785
+
786
+ @ Override
787
+ public DataBuffer write (DataBuffer ... buffers ) {
788
+ throw new UnsupportedOperationException ();
789
+ }
790
+
791
+ @ Override
792
+ public DataBuffer write (ByteBuffer ... buffers ) {
793
+ throw new UnsupportedOperationException ();
794
+ }
795
+
796
+ @ Override
797
+ public DataBuffer slice (int index , int length ) {
798
+ throw new UnsupportedOperationException ();
799
+ }
800
+
801
+ @ Override
802
+ public ByteBuffer asByteBuffer () {
803
+ throw new UnsupportedOperationException ();
804
+ }
805
+
806
+ @ Override
807
+ public ByteBuffer asByteBuffer (int index , int length ) {
808
+ throw new UnsupportedOperationException ();
809
+ }
810
+
811
+ @ Override
812
+ public InputStream asInputStream () {
813
+ throw new UnsupportedOperationException ();
814
+ }
815
+
816
+ @ Override
817
+ public InputStream asInputStream (boolean releaseOnClose ) {
818
+ throw new UnsupportedOperationException ();
819
+ }
820
+
821
+ @ Override
822
+ public OutputStream asOutputStream () {
823
+ throw new UnsupportedOperationException ();
824
+ }
825
+ }
826
+
661
827
}
0 commit comments