Skip to content

Commit 0d11049

Browse files
author
Stephane Maldini
committed
Reintroduce spec.md
1 parent 5bab96e commit 0d11049

File tree

1 file changed

+149
-1
lines changed

1 file changed

+149
-1
lines changed

tck/src/main/resources/spec.md

+149-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,151 @@
11
## Reactive-Streams Specification
22

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

Comments
 (0)