Skip to content

Commit 1ad606b

Browse files
authored
2.x: Add concatArrayEagerDelayError operator (expose feature) (#6143)
* 2.x: Add concatArrayEagerDelayError operator (expose feature) * Change text to "Concatenates an array of"
1 parent 3562dfc commit 1ad606b

File tree

5 files changed

+348
-11
lines changed

5 files changed

+348
-11
lines changed

src/main/java/io/reactivex/Flowable.java

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import org.reactivestreams.*;
1919

20+
import io.reactivex.Observable;
2021
import io.reactivex.annotations.*;
2122
import io.reactivex.disposables.Disposable;
2223
import io.reactivex.exceptions.Exceptions;
@@ -1415,7 +1416,9 @@ public static <T> Flowable<T> concatArrayDelayError(Publisher<? extends T>... so
14151416
}
14161417

14171418
/**
1418-
* Concatenates a sequence of Publishers eagerly into a single stream of values.
1419+
* Concatenates an array of Publishers eagerly into a single stream of values.
1420+
* <p>
1421+
* <img width="640" height="380" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Flowable.concatArrayEager.png" alt="">
14191422
* <p>
14201423
* Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the
14211424
* source Publishers. The operator buffers the values emitted by these Publishers and then drains them
@@ -1430,7 +1433,7 @@ public static <T> Flowable<T> concatArrayDelayError(Publisher<? extends T>... so
14301433
* <dd>This method does not operate by default on a particular {@link Scheduler}.</dd>
14311434
* </dl>
14321435
* @param <T> the value type
1433-
* @param sources a sequence of Publishers that need to be eagerly concatenated
1436+
* @param sources an array of Publishers that need to be eagerly concatenated
14341437
* @return the new Publisher instance with the specified concatenation behavior
14351438
* @since 2.0
14361439
*/
@@ -1442,7 +1445,9 @@ public static <T> Flowable<T> concatArrayEager(Publisher<? extends T>... sources
14421445
}
14431446

14441447
/**
1445-
* Concatenates a sequence of Publishers eagerly into a single stream of values.
1448+
* Concatenates an array of Publishers eagerly into a single stream of values.
1449+
* <p>
1450+
* <img width="640" height="406" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Flowable.concatArrayEager.nn.png" alt="">
14461451
* <p>
14471452
* Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the
14481453
* source Publishers. The operator buffers the values emitted by these Publishers and then drains them
@@ -1457,7 +1462,7 @@ public static <T> Flowable<T> concatArrayEager(Publisher<? extends T>... sources
14571462
* <dd>This method does not operate by default on a particular {@link Scheduler}.</dd>
14581463
* </dl>
14591464
* @param <T> the value type
1460-
* @param sources a sequence of Publishers that need to be eagerly concatenated
1465+
* @param sources an array of Publishers that need to be eagerly concatenated
14611466
* @param maxConcurrency the maximum number of concurrent subscriptions at a time, Integer.MAX_VALUE
14621467
* is interpreted as an indication to subscribe to all sources at once
14631468
* @param prefetch the number of elements to prefetch from each Publisher source
@@ -1475,6 +1480,70 @@ public static <T> Flowable<T> concatArrayEager(int maxConcurrency, int prefetch,
14751480
return RxJavaPlugins.onAssembly(new FlowableConcatMapEager(new FlowableFromArray(sources), Functions.identity(), maxConcurrency, prefetch, ErrorMode.IMMEDIATE));
14761481
}
14771482

1483+
/**
1484+
* Concatenates an array of {@link Publisher}s eagerly into a single stream of values
1485+
* and delaying any errors until all sources terminate.
1486+
* <p>
1487+
* <img width="640" height="358" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Flowable.concatArrayEagerDelayError.png" alt="">
1488+
* <p>
1489+
* Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the
1490+
* source {@code Publisher}s. The operator buffers the values emitted by these {@code Publisher}s
1491+
* and then drains them in order, each one after the previous one completes.
1492+
* <dl>
1493+
* <dt><b>Backpressure:</b></dt>
1494+
* <dd>The operator honors backpressure from downstream. The {@code Publisher}
1495+
* sources are expected to honor backpressure as well.
1496+
* If any of the source {@code Publisher}s violate this, the operator will signal a
1497+
* {@code MissingBackpressureException}.</dd>
1498+
* <dt><b>Scheduler:</b></dt>
1499+
* <dd>This method does not operate by default on a particular {@link Scheduler}.</dd>
1500+
* </dl>
1501+
* @param <T> the value type
1502+
* @param sources an array of {@code Publisher}s that need to be eagerly concatenated
1503+
* @return the new Flowable instance with the specified concatenation behavior
1504+
* @since 2.2.1 - experimental
1505+
*/
1506+
@CheckReturnValue
1507+
@SchedulerSupport(SchedulerSupport.NONE)
1508+
@BackpressureSupport(BackpressureKind.FULL)
1509+
public static <T> Flowable<T> concatArrayEagerDelayError(Publisher<? extends T>... sources) {
1510+
return concatArrayEagerDelayError(bufferSize(), bufferSize(), sources);
1511+
}
1512+
1513+
/**
1514+
* Concatenates an array of {@link Publisher}s eagerly into a single stream of values
1515+
* and delaying any errors until all sources terminate.
1516+
* <p>
1517+
* <img width="640" height="359" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Flowable.concatArrayEagerDelayError.nn.png" alt="">
1518+
* <p>
1519+
* Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the
1520+
* source {@code Publisher}s. The operator buffers the values emitted by these {@code Publisher}s
1521+
* and then drains them in order, each one after the previous one completes.
1522+
* <dl>
1523+
* <dt><b>Backpressure:</b></dt>
1524+
* <dd>The operator honors backpressure from downstream. The {@code Publisher}
1525+
* sources are expected to honor backpressure as well.
1526+
* If any of the source {@code Publisher}s violate this, the operator will signal a
1527+
* {@code MissingBackpressureException}.</dd>
1528+
* <dt><b>Scheduler:</b></dt>
1529+
* <dd>This method does not operate by default on a particular {@link Scheduler}.</dd>
1530+
* </dl>
1531+
* @param <T> the value type
1532+
* @param sources an array of {@code Publisher}s that need to be eagerly concatenated
1533+
* @param maxConcurrency the maximum number of concurrent subscriptions at a time, Integer.MAX_VALUE
1534+
* is interpreted as indication to subscribe to all sources at once
1535+
* @param prefetch the number of elements to prefetch from each {@code Publisher} source
1536+
* @return the new Flowable instance with the specified concatenation behavior
1537+
* @since 2.2.1 - experimental
1538+
*/
1539+
@SuppressWarnings({ "rawtypes", "unchecked" })
1540+
@CheckReturnValue
1541+
@SchedulerSupport(SchedulerSupport.NONE)
1542+
@BackpressureSupport(BackpressureKind.FULL)
1543+
public static <T> Flowable<T> concatArrayEagerDelayError(int maxConcurrency, int prefetch, Publisher<? extends T>... sources) {
1544+
return fromArray(sources).concatMapEagerDelayError((Function)Functions.identity(), maxConcurrency, prefetch, true);
1545+
}
1546+
14781547
/**
14791548
* Concatenates the Iterable sequence of Publishers into a single sequence by subscribing to each Publisher,
14801549
* one after the other, one at a time and delays any errors till the all inner Publishers terminate.

src/main/java/io/reactivex/Observable.java

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,19 +1294,19 @@ public static <T> Observable<T> concatArrayDelayError(ObservableSource<? extends
12941294
}
12951295

12961296
/**
1297-
* Concatenates a sequence of ObservableSources eagerly into a single stream of values.
1297+
* Concatenates an array of ObservableSources eagerly into a single stream of values.
1298+
* <p>
1299+
* <img width="640" height="410" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/concatArrayEager.png" alt="">
12981300
* <p>
12991301
* Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the
13001302
* source ObservableSources. The operator buffers the values emitted by these ObservableSources and then drains them
13011303
* in order, each one after the previous one completes.
1302-
* <p>
1303-
* <img width="640" height="410" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/concatArrayEager.png" alt="">
13041304
* <dl>
13051305
* <dt><b>Scheduler:</b></dt>
13061306
* <dd>This method does not operate by default on a particular {@link Scheduler}.</dd>
13071307
* </dl>
13081308
* @param <T> the value type
1309-
* @param sources a sequence of ObservableSources that need to be eagerly concatenated
1309+
* @param sources an array of ObservableSources that need to be eagerly concatenated
13101310
* @return the new ObservableSource instance with the specified concatenation behavior
13111311
* @since 2.0
13121312
*/
@@ -1317,7 +1317,9 @@ public static <T> Observable<T> concatArrayEager(ObservableSource<? extends T>..
13171317
}
13181318

13191319
/**
1320-
* Concatenates a sequence of ObservableSources eagerly into a single stream of values.
1320+
* Concatenates an array of ObservableSources eagerly into a single stream of values.
1321+
* <p>
1322+
* <img width="640" height="495" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/concatArrayEager.nn.png" alt="">
13211323
* <p>
13221324
* Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the
13231325
* source ObservableSources. The operator buffers the values emitted by these ObservableSources and then drains them
@@ -1327,7 +1329,7 @@ public static <T> Observable<T> concatArrayEager(ObservableSource<? extends T>..
13271329
* <dd>This method does not operate by default on a particular {@link Scheduler}.</dd>
13281330
* </dl>
13291331
* @param <T> the value type
1330-
* @param sources a sequence of ObservableSources that need to be eagerly concatenated
1332+
* @param sources an array of ObservableSources that need to be eagerly concatenated
13311333
* @param maxConcurrency the maximum number of concurrent subscriptions at a time, Integer.MAX_VALUE
13321334
* is interpreted as indication to subscribe to all sources at once
13331335
* @param prefetch the number of elements to prefetch from each ObservableSource source
@@ -1341,6 +1343,58 @@ public static <T> Observable<T> concatArrayEager(int maxConcurrency, int prefetc
13411343
return fromArray(sources).concatMapEagerDelayError((Function)Functions.identity(), maxConcurrency, prefetch, false);
13421344
}
13431345

1346+
/**
1347+
* Concatenates an array of {@link ObservableSource}s eagerly into a single stream of values
1348+
* and delaying any errors until all sources terminate.
1349+
* <p>
1350+
* <img width="640" height="354" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/concatArrayEagerDelayError.png" alt="">
1351+
* <p>
1352+
* Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the
1353+
* source {@code ObservableSource}s. The operator buffers the values emitted by these {@code ObservableSource}s
1354+
* and then drains them in order, each one after the previous one completes.
1355+
* <dl>
1356+
* <dt><b>Scheduler:</b></dt>
1357+
* <dd>This method does not operate by default on a particular {@link Scheduler}.</dd>
1358+
* </dl>
1359+
* @param <T> the value type
1360+
* @param sources an array of {@code ObservableSource}s that need to be eagerly concatenated
1361+
* @return the new Observable instance with the specified concatenation behavior
1362+
* @since 2.2.1 - experimental
1363+
*/
1364+
@CheckReturnValue
1365+
@SchedulerSupport(SchedulerSupport.NONE)
1366+
public static <T> Observable<T> concatArrayEagerDelayError(ObservableSource<? extends T>... sources) {
1367+
return concatArrayEagerDelayError(bufferSize(), bufferSize(), sources);
1368+
}
1369+
1370+
/**
1371+
* Concatenates an array of {@link ObservableSource}s eagerly into a single stream of values
1372+
* and delaying any errors until all sources terminate.
1373+
* <p>
1374+
* <img width="640" height="460" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/concatArrayEagerDelayError.nn.png" alt="">
1375+
* <p>
1376+
* Eager concatenation means that once a subscriber subscribes, this operator subscribes to all of the
1377+
* source {@code ObservableSource}s. The operator buffers the values emitted by these {@code ObservableSource}s
1378+
* and then drains them in order, each one after the previous one completes.
1379+
* <dl>
1380+
* <dt><b>Scheduler:</b></dt>
1381+
* <dd>This method does not operate by default on a particular {@link Scheduler}.</dd>
1382+
* </dl>
1383+
* @param <T> the value type
1384+
* @param sources an array of {@code ObservableSource}s that need to be eagerly concatenated
1385+
* @param maxConcurrency the maximum number of concurrent subscriptions at a time, Integer.MAX_VALUE
1386+
* is interpreted as indication to subscribe to all sources at once
1387+
* @param prefetch the number of elements to prefetch from each {@code ObservableSource} source
1388+
* @return the new Observable instance with the specified concatenation behavior
1389+
* @since 2.2.1 - experimental
1390+
*/
1391+
@SuppressWarnings({ "rawtypes", "unchecked" })
1392+
@CheckReturnValue
1393+
@SchedulerSupport(SchedulerSupport.NONE)
1394+
public static <T> Observable<T> concatArrayEagerDelayError(int maxConcurrency, int prefetch, ObservableSource<? extends T>... sources) {
1395+
return fromArray(sources).concatMapEagerDelayError((Function)Functions.identity(), maxConcurrency, prefetch, true);
1396+
}
1397+
13441398
/**
13451399
* Concatenates the Iterable sequence of ObservableSources into a single sequence by subscribing to each ObservableSource,
13461400
* one after the other, one at a time and delays any errors till the all inner ObservableSources terminate.

src/test/java/io/reactivex/internal/operators/flowable/FlowableConcatMapEagerTest.java

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,4 +1228,110 @@ public void accept(List<Integer> v)
12281228
.awaitDone(5, TimeUnit.SECONDS)
12291229
.assertResult(list);
12301230
}
1231+
1232+
@Test
1233+
public void arrayDelayErrorDefault() {
1234+
PublishProcessor<Integer> pp1 = PublishProcessor.create();
1235+
PublishProcessor<Integer> pp2 = PublishProcessor.create();
1236+
PublishProcessor<Integer> pp3 = PublishProcessor.create();
1237+
1238+
@SuppressWarnings("unchecked")
1239+
TestSubscriber<Integer> ts = Flowable.concatArrayEagerDelayError(pp1, pp2, pp3)
1240+
.test();
1241+
1242+
ts.assertEmpty();
1243+
1244+
assertTrue(pp1.hasSubscribers());
1245+
assertTrue(pp2.hasSubscribers());
1246+
assertTrue(pp3.hasSubscribers());
1247+
1248+
pp2.onNext(2);
1249+
pp2.onComplete();
1250+
1251+
ts.assertEmpty();
1252+
1253+
pp1.onNext(1);
1254+
1255+
ts.assertValuesOnly(1);
1256+
1257+
pp1.onComplete();
1258+
1259+
ts.assertValuesOnly(1, 2);
1260+
1261+
pp3.onComplete();
1262+
1263+
ts.assertResult(1, 2);
1264+
}
1265+
1266+
@Test
1267+
public void arrayDelayErrorMaxConcurrency() {
1268+
PublishProcessor<Integer> pp1 = PublishProcessor.create();
1269+
PublishProcessor<Integer> pp2 = PublishProcessor.create();
1270+
PublishProcessor<Integer> pp3 = PublishProcessor.create();
1271+
1272+
@SuppressWarnings("unchecked")
1273+
TestSubscriber<Integer> ts = Flowable.concatArrayEagerDelayError(2, 2, pp1, pp2, pp3)
1274+
.test();
1275+
1276+
ts.assertEmpty();
1277+
1278+
assertTrue(pp1.hasSubscribers());
1279+
assertTrue(pp2.hasSubscribers());
1280+
assertFalse(pp3.hasSubscribers());
1281+
1282+
pp2.onNext(2);
1283+
pp2.onComplete();
1284+
1285+
ts.assertEmpty();
1286+
1287+
pp1.onNext(1);
1288+
1289+
ts.assertValuesOnly(1);
1290+
1291+
pp1.onComplete();
1292+
1293+
assertTrue(pp3.hasSubscribers());
1294+
1295+
ts.assertValuesOnly(1, 2);
1296+
1297+
pp3.onComplete();
1298+
1299+
ts.assertResult(1, 2);
1300+
}
1301+
1302+
@Test
1303+
public void arrayDelayErrorMaxConcurrencyErrorDelayed() {
1304+
PublishProcessor<Integer> pp1 = PublishProcessor.create();
1305+
PublishProcessor<Integer> pp2 = PublishProcessor.create();
1306+
PublishProcessor<Integer> pp3 = PublishProcessor.create();
1307+
1308+
@SuppressWarnings("unchecked")
1309+
TestSubscriber<Integer> ts = Flowable.concatArrayEagerDelayError(2, 2, pp1, pp2, pp3)
1310+
.test();
1311+
1312+
ts.assertEmpty();
1313+
1314+
assertTrue(pp1.hasSubscribers());
1315+
assertTrue(pp2.hasSubscribers());
1316+
assertFalse(pp3.hasSubscribers());
1317+
1318+
pp2.onNext(2);
1319+
pp2.onError(new TestException());
1320+
1321+
ts.assertEmpty();
1322+
1323+
pp1.onNext(1);
1324+
1325+
ts.assertValuesOnly(1);
1326+
1327+
pp1.onComplete();
1328+
1329+
assertTrue(pp3.hasSubscribers());
1330+
1331+
ts.assertValuesOnly(1, 2);
1332+
1333+
pp3.onComplete();
1334+
1335+
ts.assertFailure(TestException.class, 1, 2);
1336+
}
12311337
}

0 commit comments

Comments
 (0)