Irreversibly connects two components together, and links their builders if they are not yet linked.
Returns a multiline description of the current stream graph structure, useful for debugging.
Adds this component to the graph.
Adds this component to the graph. If it's already in the graph, it's a no-op.
This doesn't link it to any other components; it's a safety measure that lets us detect any unconnected components
when build
is called.
Builds and starts a runnable FutureStream from the current graph.
Returns a Future that is fulfilled once run
has been called.
Returns a Future that is fulfilled once run
has been called.
This is useful because it allows the constructors of stream components to acquire the eventual stream and then
link it to outside failure conditions by calling RunningStream.fail
.
Builds the mutable state describing the stream graph being built, and allows building it into a runnable RunningStream.
All operations are concurrent-safe, implemented using compare-and-swap on a single AtomicReference to an immutable State. Since building a graph model usually has no performance issues, this errs in favor of correctness and catching problems early, instead of relying on the user to operate a mutable model.
If you use this explicitly, you need to: -
register
all stream components (Sources, Sinks, Connectors and Transforms) -connect
all components together, so that no Source or Sink remains unconnected -build
the runnable FutureStream.Normally, however, this class remains implicit in the background. Each StreamComponent constructor creates a new instance of this class if an existing implicit value is not provided; every shortcut method (like
Source.map
) passes its own Builder instance as the implicit parameter to the new component it creates. All components and links are registered with the builder.Whenever two different builder instances meet (by connecting two stream components that were created using separate builders), they become bidirectionally linked. Calling
build
on any of them takes all of them into account, and so it doesn't matter how the state produced byregister
andconnect
is initially distributed between them.After calling
build
once, you can keep modifying the graph (this will not affect the previously built stream), and/or callbuild
again, producing a separate stream. However, if any components are not reusable (e.g. any custom Func which is a closure over external mutable state), the behavior of the second and future streams will be undefined.