|
1 | 1 | ## Reactive-Streams Specification
|
2 | 2 |
|
3 |
| -To be determined. See https://github.com/reactive-streams/reactive-streams/issues/39 |
| 3 | +Clarification of terminology used throughout this document: |
| 4 | + |
| 5 | +* "Publisher": an implementation of the `org.reactivestreams.Publisher` interface |
| 6 | +* "Subscriber": an implementation of the `org.reactivestreams.Subscriber` interface |
| 7 | +* "Subscription": an implementation of the `org.reactivestreams.Subscription` interface |
| 8 | +* "Processor": an implementation of the `org.reactivestreams.Processor` interface |
| 9 | +* "subscriber": a Subscriber which is currently subscribed, i.e. has an active Subscription |
| 10 | +* Foo::bar: an instance method `bar` on the class `Foo` |
| 11 | + |
| 12 | + |
| 13 | +## Specification Rules |
| 14 | + |
| 15 | +### Publisher::subscribe(Subscriber) |
| 16 | + |
| 17 | +* when Publisher is in `completed` state |
| 18 | + * must not call `onSubscribe` on the given Subscriber |
| 19 | + * must trigger a call to `onComplete` on the given Subscriber |
| 20 | + |
| 21 | +* when Publisher is in `error` state |
| 22 | + * must not call `onSubscribe` on the given Subscriber |
| 23 | + * must trigger a call to `onError` on the given Subscriber |
| 24 | + |
| 25 | +* when Publisher is in `shut-down` state |
| 26 | + * must not call `onSubscribe` on the given Subscriber |
| 27 | + * must trigger a call to `onError` with a `java.lang.IllegalStateException` on the given |
| 28 | + Subscriber |
| 29 | + |
| 30 | +* when Publisher is neither in `completed`, `error` nor `shut-down` state |
| 31 | + * must trigger a call to `onSubscribe` on the given Subscriber if the Subscription is to be accepted |
| 32 | + * must trigger a call to `onError` on the given Subscriber if the Subscription is to be rejected |
| 33 | + * must reject the Subscription with a `java.lang.IllegalStateException` if the same Subscriber already |
| 34 | + has an active Subscription [1] |
| 35 | + |
| 36 | + |
| 37 | +### Subscription::request(Int) |
| 38 | + |
| 39 | +* when Subscription is cancelled |
| 40 | + * must ignore the call |
| 41 | +* when Subscription is not cancelled |
| 42 | + * must register the given number of additional elements to be produced to the respective subscriber |
| 43 | + * must throw a `java.lang.IllegalArgumentException` if the argument is <= 0 |
| 44 | + * is allowed to synchronously call `onNext` on this (or other) subscriber(s) if and only if the |
| 45 | + next element is already available |
| 46 | + * is allowed to synchronously call `onComplete` or `onError` on this (or other) subscriber(s) |
| 47 | + |
| 48 | + |
| 49 | +### Subscription::cancel |
| 50 | + |
| 51 | +* when Subscription is cancelled |
| 52 | + * must ignore the call |
| 53 | +* when Subscription is not cancelled |
| 54 | + * the Publisher must eventually cease to call any methods on the corresponding subscriber |
| 55 | + * the Publisher must eventually drop any references to the corresponding subscriber [2] |
| 56 | + * the Publisher must shut itself down if the given Subscription is the last downstream Subscription [3] |
| 57 | + |
| 58 | + |
| 59 | +### A Publisher |
| 60 | + |
| 61 | +* must not call `onNext` |
| 62 | + * more times than the total number of elements that was previously requested with |
| 63 | + Subscription::request by the corresponding subscriber |
| 64 | + * after having issued an `onComplete` or `onError` call on a subscriber |
| 65 | + |
| 66 | +* must produce the same elements in the same sequence for all its subscribers [4] |
| 67 | +* must support a pending element count up to 2^63-1 (Long.MAX_VALUE) and provide for overflow protection |
| 68 | +* must call `onComplete` on a subscriber after having produced the final stream element to it [5] |
| 69 | +* must call `onComplete` on a subscriber at the earliest possible point in time [6] |
| 70 | +* must start producing with the oldest element still available for a new subscriber |
| 71 | +* must call `onError` on all its subscribers if it encounters a non-recoverable error |
| 72 | +* must not call `onComplete` or `onError` more than once per subscriber |
| 73 | + |
| 74 | + |
| 75 | +### Subscriber::onSubscribe(Subscription), Subscriber::onNext(T) |
| 76 | + |
| 77 | +* must asynchronously schedule a respective event to the subscriber |
| 78 | +* must not call any methods on the Subscription, the Publisher or any other Publishers or Subscribers |
| 79 | + |
| 80 | + |
| 81 | +### Subscriber::onComplete, Subscriber::onError(Throwable) |
| 82 | + |
| 83 | +* must asynchronously schedule a respective event to the Subscriber |
| 84 | +* must not call any methods on the Subscription, the Publisher or any other Publishers or Subscribers |
| 85 | +* must consider the Subscription cancelled after having received the event |
| 86 | + |
| 87 | + |
| 88 | +### A Subscriber |
| 89 | + |
| 90 | +* must not accept an `onSubscribe` event if it already has an active Subscription [7] |
| 91 | +* must call Subscription::cancel during shutdown if it still has an active Subscription |
| 92 | +* must ensure that all calls on a Subscription take place from the same thread or provide for respective |
| 93 | + external synchronization [8] |
| 94 | +* must be prepared to receive one or more `onNext` events after having called Subscription::cancel [9] |
| 95 | +* must be prepared to receive an `onComplete` event with or without a preceding Subscription::request call |
| 96 | +* must be prepared to receive an `onError` event with or without a preceding Subscription::request call |
| 97 | +* must make sure that all calls on its `onXXX` methods happen-before the processing of the respective |
| 98 | + events [10] |
| 99 | + |
| 100 | + |
| 101 | +### A Processor |
| 102 | + |
| 103 | +* must obey all Publisher rules on its producing side |
| 104 | +* must obey all Subscriber rules on its consuming side |
| 105 | +* must cancel its upstream Subscription if its last downstream Subscription has been cancelled [11] |
| 106 | +* must immediately pass on `onError` events received from its upstream to its downstream [12] |
| 107 | +* must be prepared to receive incoming elements from its upstream even if a downstream subscriber has not |
| 108 | + requested anything yet |
| 109 | + |
| 110 | +### Generally |
| 111 | + |
| 112 | +* all SPI methods should neither block nor run expensive logic on the calling thread [13] |
| 113 | + |
| 114 | +### Footnotes |
| 115 | + |
| 116 | +1. Object equality is to be used for establishing whether two Subscribers are the "same". |
| 117 | + |
| 118 | +2. Cancelling a Subscription and re-subscribing the same Subscriber instance to a Publisher |
| 119 | + might fail as subscribing the same Subscriber twice is disallowed and cancel does not |
| 120 | + enforce immediate cleanup of the old subscription. In that case it will reject the |
| 121 | + Subscription with a call to `onError` with a `java.lang.IllegalStateException` in the |
| 122 | + same way as if the Subscriber already has an active Subscription. Re-subscribing with |
| 123 | + the same Subscriber instance is discouraged, but this specification does not mandate |
| 124 | + that it is disallowed since that would mean having to store previously canceled |
| 125 | + subscriptions indefinitely |
| 126 | + |
| 127 | +3. Explicitly adding "keep-alive" Subscribers can prevent automatic shutdown if required. |
| 128 | + |
| 129 | +4. Producing the stream elements at (temporarily) differing rates to different subscribers is allowed. |
| 130 | + |
| 131 | +5. The final stream element must be the same for all Subscribers. |
| 132 | + |
| 133 | +6. In particular a Publisher should not wait for another Subscription::request call before calling `onComplete` |
| 134 | + if the information that no more elements will follow is already available before. |
| 135 | + |
| 136 | +7. I.e. one Subscriber cannot be subscribed to multiple Publishers at the same time. |
| 137 | + What exactly "not accepting" means is left to the implementation but should include behavior that makes the user |
| 138 | + aware of the usage error (e.g. by logging, throwing an exception or similar). |
| 139 | + |
| 140 | +8. The Subscription implementation is not required to be thread-safe. |
| 141 | + |
| 142 | +9. if there are still requested elements pending |
| 143 | + |
| 144 | +10. I.e. the Subscriber must take care of properly publishing the event to its processing logic. |
| 145 | + ("happen-before" is used here as defined by the JLS chapter 17.4.5) |
| 146 | + |
| 147 | +11. In addition to shutting itself down as required by the Publisher rules. |
| 148 | + |
| 149 | +12. I.e. errors must not be treated as "in-stream" events that are allowed to be buffered. |
| 150 | + |
| 151 | +13. I.e. they are supposed to return control to the caller quickly. |
0 commit comments