Update image links (#24031)
This commit is contained in:
parent
3e74ca739e
commit
836f9612b8
16 changed files with 51 additions and 51 deletions
|
|
@ -377,7 +377,7 @@ The implementations shown above are the defaults provided by the @scala[`Actor`
|
||||||
<a id="actor-lifecycle"></a>
|
<a id="actor-lifecycle"></a>
|
||||||
### Actor Lifecycle
|
### Actor Lifecycle
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
A path in an actor system represents a "place" which might be occupied
|
A path in an actor system represents a "place" which might be occupied
|
||||||
by a living actor. Initially (apart from system initialized actors) a path is
|
by a living actor. Initially (apart from system initialized actors) a path is
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ but unreachability across different data centers don't influence the progress of
|
||||||
within a data center. Nodes can be added and removed also when there are network partitions between
|
within a data center. Nodes can be added and removed also when there are network partitions between
|
||||||
data centers, which is impossible if nodes are not grouped into data centers.
|
data centers, which is impossible if nodes are not grouped into data centers.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
User actions like joining, leaving, and downing can be sent to any node in the cluster,
|
User actions like joining, leaving, and downing can be sent to any node in the cluster,
|
||||||
not only to the nodes in the data center of the node. Seed nodes are also global.
|
not only to the nodes in the data center of the node. Seed nodes are also global.
|
||||||
|
|
|
||||||
|
|
@ -557,7 +557,7 @@ order to account for network issues that sometimes occur on such platforms.
|
||||||
The following chart illustrates how *phi* increase with increasing time since the
|
The following chart illustrates how *phi* increase with increasing time since the
|
||||||
previous heartbeat.
|
previous heartbeat.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Phi is calculated from the mean and standard deviation of historical
|
Phi is calculated from the mean and standard deviation of historical
|
||||||
inter arrival times. The previous chart is an example for standard deviation
|
inter arrival times. The previous chart is an example for standard deviation
|
||||||
|
|
@ -565,7 +565,7 @@ of 200 ms. If the heartbeats arrive with less deviation the curve becomes steepe
|
||||||
i.e. it is possible to determine failure more quickly. The curve looks like this for
|
i.e. it is possible to determine failure more quickly. The curve looks like this for
|
||||||
a standard deviation of 100 ms.
|
a standard deviation of 100 ms.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
To be able to survive sudden abnormalities, such as garbage collection pauses and
|
To be able to survive sudden abnormalities, such as garbage collection pauses and
|
||||||
transient network failures the failure detector is configured with a margin,
|
transient network failures the failure detector is configured with a margin,
|
||||||
|
|
@ -574,7 +574,7 @@ adjust the [configuration](#cluster-configuration) of this depending on your env
|
||||||
This is how the curve looks like for `acceptable-heartbeat-pause` configured to
|
This is how the curve looks like for `acceptable-heartbeat-pause` configured to
|
||||||
3 seconds.
|
3 seconds.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Death watch uses the cluster failure detector for nodes in the cluster, i.e. it detects
|
Death watch uses the cluster failure detector for nodes in the cluster, i.e. it detects
|
||||||
network failures and JVM crashes, in addition to graceful termination of watched
|
network failures and JVM crashes, in addition to graceful termination of watched
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ The Akka library provides an implementation of a circuit breaker called
|
||||||
- These are executed in the `ExecutionContext` provided.
|
- These are executed in the `ExecutionContext` provided.
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -259,11 +259,11 @@ members in quorum decisions.
|
||||||
|
|
||||||
#### State Diagram for the Member States (`akka.cluster.allow-weakly-up-members=off`)
|
#### State Diagram for the Member States (`akka.cluster.allow-weakly-up-members=off`)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### State Diagram for the Member States (`akka.cluster.allow-weakly-up-members=on`)
|
#### State Diagram for the Member States (`akka.cluster.allow-weakly-up-members=on`)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### Member States
|
#### Member States
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,7 @@ and then you can apply the proposed solutions as explained below.
|
||||||
|
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
In the above example we put the code under load by sending hundreds of messages to the blocking actor
|
In the above example we put the code under load by sending hundreds of messages to the blocking actor
|
||||||
which causes threads of the default dispatcher to be blocked.
|
which causes threads of the default dispatcher to be blocked.
|
||||||
|
|
@ -334,7 +334,7 @@ Java
|
||||||
|
|
||||||
The thread pool behaviour is shown in the below diagram.
|
The thread pool behaviour is shown in the below diagram.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Messages sent to `SeparateDispatcherFutureActor` and `PrintActor` are easily handled by the default dispatcher - the
|
Messages sent to `SeparateDispatcherFutureActor` and `PrintActor` are easily handled by the default dispatcher - the
|
||||||
green lines, which represent the actual execution.
|
green lines, which represent the actual execution.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<a id="fault-tolerance-sample"></a>
|
<a id="fault-tolerance-sample"></a>
|
||||||
# Diagrams of the Fault Tolerance Sample
|
# Diagrams of the Fault Tolerance Sample
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
*The above diagram illustrates the normal message flow.*
|
*The above diagram illustrates the normal message flow.*
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
|3, 4, 5 | When receiving `Do` the `Worker` tells the `CounterService` to increment the counter, three times. The `Increment` message is forwarded to the `Counter`, which updates its counter variable and sends current value to the `Storage`.|
|
|3, 4, 5 | When receiving `Do` the `Worker` tells the `CounterService` to increment the counter, three times. The `Increment` message is forwarded to the `Counter`, which updates its counter variable and sends current value to the `Storage`.|
|
||||||
|6, 7 | The `Worker` asks the `CounterService` of current value of the counter and pipes the result back to the `Listener`. |
|
|6, 7 | The `Worker` asks the `CounterService` of current value of the counter and pipes the result back to the `Listener`. |
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
*The above diagram illustrates what happens in case of storage failure.*
|
*The above diagram illustrates what happens in case of storage failure.*
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ test nodes)
|
||||||
|
|
||||||
This is a schematic overview of the test conductor.
|
This is a schematic overview of the test conductor.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The test conductor server is responsible for coordinating barriers and sending commands to the test conductor
|
The test conductor server is responsible for coordinating barriers and sending commands to the test conductor
|
||||||
clients that act upon them, e.g. throttling network traffic to/from another client. More information on the
|
clients that act upon them, e.g. throttling network traffic to/from another client. More information on the
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ datastore understands directly.
|
||||||
The below figure explains how the default serialization scheme works, and how it fits together with serializing the
|
The below figure explains how the default serialization scheme works, and how it fits together with serializing the
|
||||||
user provided message itself, which we will from here on refer to as the `payload` (highlighted in yellow):
|
user provided message itself, which we will from here on refer to as the `payload` (highlighted in yellow):
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Akka Persistence provided serializers wrap the user payload in an envelope containing all persistence-relevant information.
|
Akka Persistence provided serializers wrap the user payload in an envelope containing all persistence-relevant information.
|
||||||
**If the Journal uses provided Protobuf serializers for the wrapper types (e.g. PersistentRepr), then the payload will
|
**If the Journal uses provided Protobuf serializers for the wrapper types (e.g. PersistentRepr), then the payload will
|
||||||
|
|
@ -249,7 +249,7 @@ representation of the message. This is one of the advantages of schema based ser
|
||||||
add the overhead of having to maintain the schema. When using serializers like this, no additional code change
|
add the overhead of having to maintain the schema. When using serializers like this, no additional code change
|
||||||
(except renaming the field and method used during serialization) is needed to perform such evolution:
|
(except renaming the field and method used during serialization) is needed to perform such evolution:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
This is how such a rename would look in protobuf:
|
This is how such a rename would look in protobuf:
|
||||||
|
|
||||||
|
|
@ -277,7 +277,7 @@ This approach is popular when your serialization format is something like JSON,
|
||||||
automatically by the serializer. You can do these kinds of "promotions" either manually (as shown in the example below)
|
automatically by the serializer. You can do these kinds of "promotions" either manually (as shown in the example below)
|
||||||
or using a library like @scala[[Stamina](https://github.com/scalapenos/stamina)]@java[[Stamina](https://github.com/javapenos/stamina)] which helps to create those `V1->V2->V3->...->Vn` promotion chains without much boilerplate.
|
or using a library like @scala[[Stamina](https://github.com/scalapenos/stamina)]@java[[Stamina](https://github.com/javapenos/stamina)] which helps to create those `V1->V2->V3->...->Vn` promotion chains without much boilerplate.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The following snippet showcases how one could apply renames if working with plain JSON (using @scala[`spray.json.JsObject`]@java[a `JsObject` as an example JSON representation]):
|
The following snippet showcases how one could apply renames if working with plain JSON (using @scala[`spray.json.JsObject`]@java[a `JsObject` as an example JSON representation]):
|
||||||
|
|
||||||
|
|
@ -313,7 +313,7 @@ The problem of removing an event type from the domain model is not as much its r
|
||||||
for the recovery mechanisms that this entails. For example, a naive way of filtering out certain kinds of events from
|
for the recovery mechanisms that this entails. For example, a naive way of filtering out certain kinds of events from
|
||||||
being delivered to a recovering `PersistentActor` is pretty simple, as one can simply filter them out in an @ref:[EventAdapter](persistence.md#event-adapters):
|
being delivered to a recovering `PersistentActor` is pretty simple, as one can simply filter them out in an @ref:[EventAdapter](persistence.md#event-adapters):
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The `EventAdapter` can drop old events (**O**) by emitting an empty `EventSeq`.
|
The `EventAdapter` can drop old events (**O**) by emitting an empty `EventSeq`.
|
||||||
Other events can simply be passed through (**E**).
|
Other events can simply be passed through (**E**).
|
||||||
|
|
@ -342,7 +342,7 @@ This can for example be implemented by using an `SerializerWithStringManifest`
|
||||||
(documented in depth in @ref:[Serializer with String Manifest](serialization.md#string-manifest-serializer)). By looking at the string manifest, the serializer can notice
|
(documented in depth in @ref:[Serializer with String Manifest](serialization.md#string-manifest-serializer)). By looking at the string manifest, the serializer can notice
|
||||||
that the type is no longer needed, and skip the deserialization all-together:
|
that the type is no longer needed, and skip the deserialization all-together:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The serializer is aware of the old event types that need to be skipped (**O**), and can skip deserializing them alltogether
|
The serializer is aware of the old event types that need to be skipped (**O**), and can skip deserializing them alltogether
|
||||||
by simply returning a "tombstone" (**T**), which the EventAdapter converts into an empty EventSeq.
|
by simply returning a "tombstone" (**T**), which the EventAdapter converts into an empty EventSeq.
|
||||||
|
|
@ -384,7 +384,7 @@ classes which very often may be less user-friendly yet highly optimised for thro
|
||||||
(like the classes generated by protobuf for example), it is possible to use a simple EventAdapter which maps between
|
(like the classes generated by protobuf for example), it is possible to use a simple EventAdapter which maps between
|
||||||
these types in a 1:1 style as illustrated below:
|
these types in a 1:1 style as illustrated below:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Domain events (**A**) are adapted to the data model events (**D**) by the `EventAdapter`.
|
Domain events (**A**) are adapted to the data model events (**D**) by the `EventAdapter`.
|
||||||
The data model can be a format natively understood by the journal, such that it can store it more efficiently or
|
The data model can be a format natively understood by the journal, such that it can store it more efficiently or
|
||||||
|
|
@ -478,7 +478,7 @@ The write side change is very simple, we simply persist `UserNameChanged` or `Us
|
||||||
on what the user actually intended to change (instead of the composite `UserDetailsChanged` that we had in version 1
|
on what the user actually intended to change (instead of the composite `UserDetailsChanged` that we had in version 1
|
||||||
of our model).
|
of our model).
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The `EventAdapter` splits the incoming event into smaller more fine grained events during recovery.
|
The `EventAdapter` splits the incoming event into smaller more fine grained events during recovery.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -491,7 +491,7 @@ order to account for network issues that sometimes occur on such platforms.
|
||||||
The following chart illustrates how *phi* increase with increasing time since the
|
The following chart illustrates how *phi* increase with increasing time since the
|
||||||
previous heartbeat.
|
previous heartbeat.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Phi is calculated from the mean and standard deviation of historical
|
Phi is calculated from the mean and standard deviation of historical
|
||||||
inter arrival times. The previous chart is an example for standard deviation
|
inter arrival times. The previous chart is an example for standard deviation
|
||||||
|
|
@ -499,7 +499,7 @@ of 200 ms. If the heartbeats arrive with less deviation the curve becomes steepe
|
||||||
i.e. it is possible to determine failure more quickly. The curve looks like this for
|
i.e. it is possible to determine failure more quickly. The curve looks like this for
|
||||||
a standard deviation of 100 ms.
|
a standard deviation of 100 ms.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
To be able to survive sudden abnormalities, such as garbage collection pauses and
|
To be able to survive sudden abnormalities, such as garbage collection pauses and
|
||||||
transient network failures the failure detector is configured with a margin,
|
transient network failures the failure detector is configured with a margin,
|
||||||
|
|
@ -508,7 +508,7 @@ adjust the [Remote Configuration](#remote-configuration-artery) of this dependin
|
||||||
This is how the curve looks like for `acceptable-heartbeat-pause` configured to
|
This is how the curve looks like for `acceptable-heartbeat-pause` configured to
|
||||||
3 seconds.
|
3 seconds.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Serialization
|
## Serialization
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,7 @@ Actor classes not included in the whitelist will not be allowed to be remote dep
|
||||||
|
|
||||||
## Lifecycle and Failure Recovery Model
|
## Lifecycle and Failure Recovery Model
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Each link with a remote system can be in one of the four states as illustrated above. Before any communication
|
Each link with a remote system can be in one of the four states as illustrated above. Before any communication
|
||||||
happens with a remote system at a given `Address` the state of the association is `Idle`. The first time a message
|
happens with a remote system at a given `Address` the state of the association is `Idle`. The first time a message
|
||||||
|
|
@ -311,7 +311,7 @@ order to account for network issues that sometimes occur on such platforms.
|
||||||
The following chart illustrates how *phi* increase with increasing time since the
|
The following chart illustrates how *phi* increase with increasing time since the
|
||||||
previous heartbeat.
|
previous heartbeat.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Phi is calculated from the mean and standard deviation of historical
|
Phi is calculated from the mean and standard deviation of historical
|
||||||
inter arrival times. The previous chart is an example for standard deviation
|
inter arrival times. The previous chart is an example for standard deviation
|
||||||
|
|
@ -319,7 +319,7 @@ of 200 ms. If the heartbeats arrive with less deviation the curve becomes steepe
|
||||||
i.e. it is possible to determine failure more quickly. The curve looks like this for
|
i.e. it is possible to determine failure more quickly. The curve looks like this for
|
||||||
a standard deviation of 100 ms.
|
a standard deviation of 100 ms.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
To be able to survive sudden abnormalities, such as garbage collection pauses and
|
To be able to survive sudden abnormalities, such as garbage collection pauses and
|
||||||
transient network failures the failure detector is configured with a margin,
|
transient network failures the failure detector is configured with a margin,
|
||||||
|
|
@ -328,7 +328,7 @@ adjust the [Remote Configuration](#remote-configuration) of this depending on yo
|
||||||
This is how the curve looks like for `acceptable-heartbeat-pause` configured to
|
This is how the curve looks like for `acceptable-heartbeat-pause` configured to
|
||||||
3 seconds.
|
3 seconds.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Serialization
|
## Serialization
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ be processed arrive and leave the stage. In this view, a `Source` is nothing els
|
||||||
output port, or, a `BidiFlow` is a "box" with exactly two input and two output ports. In the figure below
|
output port, or, a `BidiFlow` is a "box" with exactly two input and two output ports. In the figure below
|
||||||
we illustrate the most common used stages viewed as "boxes".
|
we illustrate the most common used stages viewed as "boxes".
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The *linear* stages are `Source`, `Sink`
|
The *linear* stages are `Source`, `Sink`
|
||||||
and `Flow`, as these can be used to compose strict chains of processing stages.
|
and `Flow`, as these can be used to compose strict chains of processing stages.
|
||||||
|
|
@ -31,7 +31,7 @@ to interact with. One good example is the `Http` server component, which is enco
|
||||||
The following figure demonstrates various composite stages, that contain various other type of stages internally, but
|
The following figure demonstrates various composite stages, that contain various other type of stages internally, but
|
||||||
hiding them behind a *shape* that looks like a `Source`, `Flow`, etc.
|
hiding them behind a *shape* that looks like a `Source`, `Flow`, etc.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
One interesting example above is a `Flow` which is composed of a disconnected `Sink` and `Source`.
|
One interesting example above is a `Flow` which is composed of a disconnected `Sink` and `Source`.
|
||||||
This can be achieved by using the `fromSinkAndSource()` constructor method on `Flow` which takes the two parts as
|
This can be achieved by using the `fromSinkAndSource()` constructor method on `Flow` which takes the two parts as
|
||||||
|
|
@ -54,7 +54,7 @@ These mechanics allow arbitrary nesting of modules. For example the following fi
|
||||||
that is built from a composite `Source` and a composite `Sink` (which in turn contains a composite
|
that is built from a composite `Source` and a composite `Sink` (which in turn contains a composite
|
||||||
`Flow`).
|
`Flow`).
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The above diagram contains one more shape that we have not seen yet, which is called `RunnableGraph`. It turns
|
The above diagram contains one more shape that we have not seen yet, which is called `RunnableGraph`. It turns
|
||||||
out, that if we wire all exposed ports together, so that no more open ports remain, we get a module that is *closed*.
|
out, that if we wire all exposed ports together, so that no more open ports remain, we get a module that is *closed*.
|
||||||
|
|
@ -90,7 +90,7 @@ Once we have hidden the internals of our components, they act like any other bui
|
||||||
we hide some of the internals of our composites, the result looks just like if any other predefine component has been
|
we hide some of the internals of our composites, the result looks just like if any other predefine component has been
|
||||||
used:
|
used:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
If we look at usage of built-in components, and our custom components, there is no difference in usage as the code
|
If we look at usage of built-in components, and our custom components, there is no difference in usage as the code
|
||||||
snippet below demonstrates.
|
snippet below demonstrates.
|
||||||
|
|
@ -112,7 +112,7 @@ operate on are uniform across all DSLs and fit together nicely.
|
||||||
|
|
||||||
As a first example, let's look at a more complex layout:
|
As a first example, let's look at a more complex layout:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The diagram shows a `RunnableGraph` (remember, if there are no unwired ports, the graph is closed, and therefore
|
The diagram shows a `RunnableGraph` (remember, if there are no unwired ports, the graph is closed, and therefore
|
||||||
can be materialized) that encapsulates a non-trivial stream processing network. It contains fan-in, fan-out stages,
|
can be materialized) that encapsulates a non-trivial stream processing network. It contains fan-in, fan-out stages,
|
||||||
|
|
@ -140,7 +140,7 @@ the layout is flat, not modularized. We will modify our example, and create a re
|
||||||
The way to do it is to use the `create()` factory method on `GraphDSL`. If we remove the sources and sinks
|
The way to do it is to use the `create()` factory method on `GraphDSL`. If we remove the sources and sinks
|
||||||
from the previous example, what remains is a partial graph:
|
from the previous example, what remains is a partial graph:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
We can recreate a similar graph in code, using the DSL in a similar way than before:
|
We can recreate a similar graph in code, using the DSL in a similar way than before:
|
||||||
|
|
||||||
|
|
@ -159,7 +159,7 @@ matching built-in ones.
|
||||||
The resulting graph is already a properly wrapped module, so there is no need to call *named()* to encapsulate the graph, but
|
The resulting graph is already a properly wrapped module, so there is no need to call *named()* to encapsulate the graph, but
|
||||||
it is a good practice to give names to modules to help debugging.
|
it is a good practice to give names to modules to help debugging.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Since our partial graph has the right shape, it can be already used in the simpler, linear DSL:
|
Since our partial graph has the right shape, it can be already used in the simpler, linear DSL:
|
||||||
|
|
||||||
|
|
@ -175,7 +175,7 @@ has a `fromGraph()` method that just adds the DSL to a `FlowShape`. There are si
|
||||||
For convenience, it is also possible to skip the partial graph creation, and use one of the convenience creator methods.
|
For convenience, it is also possible to skip the partial graph creation, and use one of the convenience creator methods.
|
||||||
To demonstrate this, we will create the following graph:
|
To demonstrate this, we will create the following graph:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The code version of the above closed graph might look like this:
|
The code version of the above closed graph might look like this:
|
||||||
|
|
||||||
|
|
@ -239,7 +239,7 @@ We demonstrate how this works by a code example and a diagram which graphically
|
||||||
|
|
||||||
The propagation of the individual materialized values from the enclosed modules towards the top will look like this:
|
The propagation of the individual materialized values from the enclosed modules towards the top will look like this:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
To implement the above, first, we create a composite `Source`, where the enclosed `Source` have a
|
To implement the above, first, we create a composite `Source`, where the enclosed `Source` have a
|
||||||
materialized type of @scala[`Promise[[Option[Int]]`] @java[`CompletableFuture<Optional<Integer>>>`]. By using the combiner function `Keep.left`, the resulting materialized
|
materialized type of @scala[`Promise[[Option[Int]]`] @java[`CompletableFuture<Optional<Integer>>>`]. By using the combiner function `Keep.left`, the resulting materialized
|
||||||
|
|
@ -317,7 +317,7 @@ the same attribute explicitly set. `nestedSource` gets the default attributes fr
|
||||||
on the other hand has this attribute set, so it will be used by all nested modules. `nestedFlow` will inherit from `nestedSink`
|
on the other hand has this attribute set, so it will be used by all nested modules. `nestedFlow` will inherit from `nestedSink`
|
||||||
except the `map` stage which has again an explicitly provided attribute overriding the inherited one.
|
except the `map` stage which has again an explicitly provided attribute overriding the inherited one.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
This diagram illustrates the inheritance process for the example code (representing the materializer default attributes
|
This diagram illustrates the inheritance process for the example code (representing the materializer default attributes
|
||||||
as the color *red*, the attributes set on `nestedSink` as *blue* and the attributes set on `nestedFlow` as *green*).
|
as the color *red*, the attributes set on `nestedSink` as *blue* and the attributes set on `nestedFlow` as *green*).
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ the initial state while orange indicates the end state. If an operation is not l
|
||||||
to call it while the port is in that state. If an event is not listed for a state, then that event cannot happen
|
to call it while the port is in that state. If an event is not listed for a state, then that event cannot happen
|
||||||
in that state.
|
in that state.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The following operations are available for *input* ports:
|
The following operations are available for *input* ports:
|
||||||
|
|
||||||
|
|
@ -140,7 +140,7 @@ the initial state while orange indicates the end state. If an operation is not l
|
||||||
to call it while the port is in that state. If an event is not listed for a state, then that event cannot happen
|
to call it while the port is in that state. If an event is not listed for a state, then that event cannot happen
|
||||||
in that state.
|
in that state.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Finally, there are two methods available for convenience to complete the stage and all of its ports:
|
Finally, there are two methods available for convenience to complete the stage and all of its ports:
|
||||||
|
|
||||||
|
|
@ -178,11 +178,11 @@ Such a stage can be illustrated as a box with two flows as it is
|
||||||
seen in the illustration below. Demand flowing upstream leading to elements
|
seen in the illustration below. Demand flowing upstream leading to elements
|
||||||
flowing downstream.
|
flowing downstream.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
To illustrate these concepts we create a small `GraphStage` that implements the `map` transformation.
|
To illustrate these concepts we create a small `GraphStage` that implements the `map` transformation.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Map calls `push(out)` from the `onPush()` handler and it also calls `pull()` from the `onPull` handler resulting in the
|
Map calls `push(out)` from the `onPush()` handler and it also calls `pull()` from the `onPull` handler resulting in the
|
||||||
conceptual wiring above, and fully expressed in code below:
|
conceptual wiring above, and fully expressed in code below:
|
||||||
|
|
@ -199,7 +199,7 @@ demand is passed along upstream elements passed on downstream.
|
||||||
To demonstrate a many-to-one stage we will implement
|
To demonstrate a many-to-one stage we will implement
|
||||||
filter. The conceptual wiring of `Filter` looks like this:
|
filter. The conceptual wiring of `Filter` looks like this:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
As we see above, if the given predicate matches the current element we are propagating it downwards, otherwise
|
As we see above, if the given predicate matches the current element we are propagating it downwards, otherwise
|
||||||
we return the “ball” to our upstream so that we get the new element. This is achieved by modifying the map
|
we return the “ball” to our upstream so that we get the new element. This is achieved by modifying the map
|
||||||
|
|
@ -215,7 +215,7 @@ Java
|
||||||
To complete the picture we define a one-to-many transformation as the next step. We chose a straightforward example stage
|
To complete the picture we define a one-to-many transformation as the next step. We chose a straightforward example stage
|
||||||
that emits every upstream element twice downstream. The conceptual wiring of this stage looks like this:
|
that emits every upstream element twice downstream. The conceptual wiring of this stage looks like this:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
This is a stage that has state: an option with the last element it has seen indicating if it
|
This is a stage that has state: an option with the last element it has seen indicating if it
|
||||||
has duplicated this last element already or not. We must also make sure to emit the extra element
|
has duplicated this last element already or not. We must also make sure to emit the extra element
|
||||||
|
|
@ -247,7 +247,7 @@ Java
|
||||||
Finally, to demonstrate all of the stages above, we put them together into a processing chain,
|
Finally, to demonstrate all of the stages above, we put them together into a processing chain,
|
||||||
which conceptually would correspond to the following structure:
|
which conceptually would correspond to the following structure:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
In code this is only a few lines, using the `via` use our custom stages in a stream:
|
In code this is only a few lines, using the `via` use our custom stages in a stream:
|
||||||
|
|
||||||
|
|
@ -260,7 +260,7 @@ Java
|
||||||
If we attempt to draw the sequence of events, it shows that there is one "event token"
|
If we attempt to draw the sequence of events, it shows that there is one "event token"
|
||||||
in circulation in a potential chain of stages, just like our conceptual "railroad tracks" representation predicts.
|
in circulation in a potential chain of stages, just like our conceptual "railroad tracks" representation predicts.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Completion
|
### Completion
|
||||||
|
|
||||||
|
|
@ -432,12 +432,12 @@ The next diagram illustrates the event sequence for a buffer with capacity of tw
|
||||||
the downstream demand is slow to start and the buffer will fill up with upstream elements before any demand
|
the downstream demand is slow to start and the buffer will fill up with upstream elements before any demand
|
||||||
is seen from downstream.
|
is seen from downstream.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Another scenario would be where the demand from downstream starts coming in before any element is pushed
|
Another scenario would be where the demand from downstream starts coming in before any element is pushed
|
||||||
into the buffer stage.
|
into the buffer stage.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The first difference we can notice is that our `Buffer` stage is automatically pulling its upstream on
|
The first difference we can notice is that our `Buffer` stage is automatically pulling its upstream on
|
||||||
initialization. The buffer has demand for up to two elements without any downstream demand.
|
initialization. The buffer has demand for up to two elements without any downstream demand.
|
||||||
|
|
|
||||||
|
|
@ -296,7 +296,7 @@ work on the tasks in parallel. It is important to note that asynchronous boundar
|
||||||
flow where elements are passed asynchronously (as in other streaming libraries), but instead attributes always work
|
flow where elements are passed asynchronously (as in other streaming libraries), but instead attributes always work
|
||||||
by adding information to the flow graph that has been constructed up to this point:
|
by adding information to the flow graph that has been constructed up to this point:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
This means that everything that is inside the red bubble will be executed by one actor and everything outside of it
|
This means that everything that is inside the red bubble will be executed by one actor and everything outside of it
|
||||||
by another. This scheme can be applied successively, always having one such boundary enclose the previous ones plus all
|
by another. This scheme can be applied successively, always having one such boundary enclose the previous ones plus all
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ One of the goals of the GraphDSL DSL is to look similar to how one would draw a
|
||||||
simple to translate a design from whiteboard to code and be able to relate those two. Let's illustrate this by translating
|
simple to translate a design from whiteboard to code and be able to relate those two. Let's illustrate this by translating
|
||||||
the below hand drawn graph into Akka Streams:
|
the below hand drawn graph into Akka Streams:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Such graph is simple to translate to the Graph DSL since each linear element corresponds to a `Flow`,
|
Such graph is simple to translate to the Graph DSL since each linear element corresponds to a `Flow`,
|
||||||
and each circle corresponds to either a `Junction` or a `Source` or `Sink` if it is beginning
|
and each circle corresponds to either a `Junction` or a `Source` or `Sink` if it is beginning
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ Scala
|
||||||
Java
|
Java
|
||||||
: @@snip [StreamTcpDocTest.java]($code$/java/jdocs/stream/io/StreamTcpDocTest.java) { #echo-server-simple-bind }
|
: @@snip [StreamTcpDocTest.java]($code$/java/jdocs/stream/io/StreamTcpDocTest.java) { #echo-server-simple-bind }
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Next, we simply handle *each* incoming connection using a `Flow` which will be used as the processing stage
|
Next, we simply handle *each* incoming connection using a `Flow` which will be used as the processing stage
|
||||||
to handle and emit `ByteString` s from and to the TCP Socket. Since one `ByteString` does not have to necessarily
|
to handle and emit `ByteString` s from and to the TCP Socket. Since one `ByteString` does not have to necessarily
|
||||||
|
|
@ -33,7 +33,7 @@ Scala
|
||||||
Java
|
Java
|
||||||
: @@snip [StreamTcpDocTest.java]($code$/java/jdocs/stream/io/StreamTcpDocTest.java) { #echo-server-simple-handle }
|
: @@snip [StreamTcpDocTest.java]($code$/java/jdocs/stream/io/StreamTcpDocTest.java) { #echo-server-simple-handle }
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Notice that while most building blocks in Akka Streams are reusable and freely shareable, this is *not* the case for the
|
Notice that while most building blocks in Akka Streams are reusable and freely shareable, this is *not* the case for the
|
||||||
incoming connection Flow, since it directly corresponds to an existing, already accepted connection its handling can
|
incoming connection Flow, since it directly corresponds to an existing, already accepted connection its handling can
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue