Skip to content

Commit 14cc69c

Browse files
authored
Merge pull request #86 from jroper/streams-images
More work on streams images
2 parents 0d74f16 + d52d277 commit 14cc69c

17 files changed

+975
-28
lines changed

pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@
197197
</executions>
198198
<configuration>
199199
<excludes>
200+
<exclude>**/*.svg</exclude>
201+
<exclude>**/target</exclude>
200202
<exclude>.travis.yml.*</exclude>
201203
<exclude>bnd.bnd</exclude>
202204
<exclude>*.log</exclude>

streams/spec/pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
</goals>
6565
<configuration>
6666
<backend>pdf</backend>
67+
<imagesDir>.</imagesDir>
6768
<attributes>
6869
<revnumber>${project.version}</revnumber>
6970
<revremark>${revremark}</revremark>
@@ -79,6 +80,7 @@
7980
</goals>
8081
<configuration>
8182
<backend>html5</backend>
83+
<imagesDir>.</imagesDir>
8284
<attributes>
8385
<revnumber>${project.version}</revnumber>
8486
<revremark>${revremark}</revremark>

streams/spec/src/main/asciidoc/architecture.asciidoc

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -71,51 +71,70 @@ Methods that accept a `org.reactivestreams` interface do not need to be given th
7171
== Design
7272

7373
The design of MicroProfile Reactive Streams is centered around **builders** for the various shapes of streams.
74-
There are four different shapes of streams that can be built:
74+
Each builder contains zero or more stages. There are three different shapes of stages:
7575

76-
* Processors. A processor has one inlet and one outlet, and is represented as a Reactive Streams `Processor` when built. This is called a `ProcessorBuilder`.
76+
* Publisher. A publisher stage has an outlet, but no inlet.
7777

78-
* Publishers. A publisher has one outlet but no inlet, and is represented as a Reactive Streams `Publisher` when built. This is called a `PublisherBuilder`
78+
image::images/publisher-stage.svg[Publisher stage,width=200,align="center"]
7979

80-
* Subscribers. A subscriber has one inlet but no outlet, and it also has a result. It is represented as a product of a Reactive Streams `Subscriber` and a `CompletionStage` that is redeemed with the result, or error if the stream fails, when built. This is called a `SubscriberBuilder`.
80+
* Processor. A processor stage has an inlet and an outlet.
8181

82-
image::shapes.png[Shapes,400,400,align="center"]
82+
image::images/processor-stage.svg[Processor stage,width=250,align="center"]
8383

84-
* Closed graphs. A closed graph has no inlet or outlet, both having being provided in during the construction of the graph
85-
. It is represented as a `CompletionStage` of the result of the stream. This is called a `CompletionRunner`. The result is
86-
retrieved using the `run` method.
84+
* Subscriber. A subscriber stage has an inlet, but no outlet.
8785

88-
image::graph.png[Closed graph,250,250,align="center"]
86+
image::images/subscriber-stage.svg[Subscriber stage,width=180,align="center"]
8987

90-
While building a stream, the stream may change shape during its construction.
91-
For example, a publisher may be collected into a `List` of elements.
92-
When this happens, the stream becomes a closed graph, since there is no longer an outlet, but just a result, the result being the `List` of elements:
88+
Stream stages can be built into graphs, using the builders. There are four different shapes of graphs that can be built:
9389

94-
[source, java]
95-
----
96-
PublisherBuilder<Integer> intsPublisher =
97-
ReactiveStreams.of(1, 2, 3); <1>
90+
* Publishers. A publisher has one outlet but no inlet, and is represented as a Reactive Streams `Publisher` when built.
91+
It contains one publisher stage, followed by zero or more processor stages. This is called a `PublisherBuilder`
9892

99-
CompletionRunner<List<Integer>> intsResult =
100-
intsPublisher.toList(); <2>
101-
----
102-
<1> A publisher of integers 1, 2 and 3.
103-
<2> A closed graph that emits all the received integers as a result.
93+
image::images/publisher-builder.svg[Publisher,width=320,align="center"]
94+
95+
* Processors. A processor has one inlet and one outlet, and is represented as a Reactive Streams `Processor` when built.
96+
It contains zero or more processor stages. This is called a `ProcessorBuilder`.
97+
98+
image::images/processor-builder.svg[Processor,width=350,align="center"]
99+
100+
* Subscribers. A subscriber has one inlet but no outlet, and it also has a result.
101+
It is represented as a product of a Reactive Streams `Subscriber` and a `CompletionStage` that is redeemed with the result, or error if the stream fails, when built.
102+
It contains zero or more processor stages, followed by a single subscriber stage. This is called a `SubscriberBuilder`.
104103

104+
image::images/subscriber-builder.svg[Subscriber,width=300,align="center"]
105105

106-
Or, a processor may be plumbed to a subscriber, in which case, the resulting builder is now a subscriber:
106+
* Closed graphs. A closed graph has no inlet or outlet, both having being provided in during the construction of the graph.
107+
It is represented as a `CompletionStage` of the result of the stream.
108+
It contains a publisher stage, followed by zero or more processor stages, followed by a subscriber stage.
109+
This is called a `CompletionRunner`. The result is retrieved using the `run` method.
110+
111+
image::images/closed-graph-builder.svg[Closed graph,width=420,align="center"]
112+
113+
While building a stream, the stream may change shape during its construction.
114+
For example, a publisher may be collected into a `List` of elements.
115+
When this happens, the stream becomes a closed graph, since there is no longer an outlet, but just a result, the result being the `List` of elements:
116+
117+
Here's an example of a more complex situation where a `PublisherBuilder` is plumbed to a `SubscriberBuilder`, producing a `CompletionRunner`:
107118

108119
[source, java]
109120
----
110-
ProcessorBuilder<Integer, String> toStringProcessor =
121+
PublisherBuilder<Integer> evenIntsPublisher =
122+
ReactiveStreams.of(1, 2, 3, 4)
123+
.filter(i -> i % 2 == 0); <1>
124+
125+
SubscriberBuilder<Integer, List<Integer>> doublingSubscriber =
111126
ReactiveStreams.<Integer>builder()
112-
.map(Object::toString); <1>
127+
.map(i -> i = i * 2)
128+
.toList(); <2>
113129
114-
SubscriberBuilder<Integer, List<String>> toListSubscriber =
115-
toStringProcessor.toList(); <2>
130+
CompletionRunner<List<Integer>> result =
131+
eventIntsPublisher.to(doublingSubscriber); <3>
116132
----
117-
<1> A processor that receives integers and emits them as strings.
118-
<2> A subscriber that receives integers, and emits all the integers as Strings in a List when the stream completes.
133+
<1> A publisher of integers 2 and 4.
134+
<2> A subscriber that first doubles integers, then collects into a list.
135+
<3> A closed graph that when run, will produce the result in a `CompletionStage`.
136+
137+
image::images/change-shape.svg[Combining two graphs,width=600,align="center"]
119138

120139
When MicroProfile specifications provide an API that uses Reactive Streams, it is intended that application developers can return and pass the builder interfaces directly to the MicroProfile APIs.
121140
In many cases, application developers will not need to run the streams themselves.

0 commit comments

Comments
 (0)