A FlowBuilder provides tools for cunstructing an akka.stream Flow that transforms a FlowResult into another FlowResult.
A FlowBuilder provides tools for cunstructing an akka.stream Flow that transforms a FlowResult into another FlowResult. More explicitly, it is used to construct a Flow[FlowResult[I, Ctx], FlowResult[T, Ctx], akka.NotUsed]. Here I is thought of as the initial or input type, T is the terminal or output type, and Ctx is the context type which remains unchanged throughout the flow.
We prefer to transform FlowResults rather than the raw types I and T because it allows us to carry along all the extra information contained in the FlowResult. Namely, the context, the success/failure status, and the metadata. FlowBuilder makes it easy to transform the underlying types without affecting this context, and will transparently propogate failures.
val flow: Flow[FlowResult[Int, Int], FlowResult[String, Int], akka.NotUsed] = FlowBuilder.simple[Int] .map(i => i * 2) .flatMap { case i if i < 0 => Failure(new Exception("number is negative!")) case i => Success(i) }.mapWithContext((i, context, metadata) => s"Value: $i, Context: $context") .flow This starts with an initial Flow containing FlowResults of integers (and with context as the initia int value). It then:
A FlowResult[T, Ctx] is a Try[T] with an associated context and metadata that are are automatically carried along with each transformation applied to the FlowResult.
A FlowResult[T, Ctx] is a Try[T] with an associated context and metadata that are are automatically carried along with each transformation applied to the FlowResult. It is meant to be used as part of an akka.streams Stream, making it easy for additional information about an item passing through the stream to be propogated.
MergeFlow provides a way to apply branching logic to a flow.
MergeFlow provides a way to apply branching logic to a flow. It works as follows: with each flow, you assign a predicate that determines the conditions under which that flow should be applied. Generally, these predicates should be mutually exclusive and cover all possible cases, but this is not enforced. Together, these form a list of flow-predicate pairs. From these, a new flow is constructed, in which (in order) - Each item in the flow is broadcast to N child flows - Each child flow is filtered according to the associated predicate. - The items for which the predicate is true are passed down the associated flow. - Items that are errors (and hence to which none of the predicates apply) are propogated in another error flow. - The items in each flow are merged back into a single flow.
+------------+ | | | Broadcast | | | +------+-----+ /|\ / | \ / | \ / | \ / | \ / | \ / | \ / | \ +----------+ +-------+ +-------------+ |Predicate | | ... | | Errors | |1 Applied | | | | Propgated | | | | | | | +-----+----+ +---+---+ +------+------+ | | | | | | +-----+----+ +---+---+ / | Flow 1 | | Flows | / | | | | / +-----\----+ +---+---+ / \ | / \ | / \ | / \ | / \ | / \ | / \ | / \ | / \ |/ +----------------+ | | | Merge | | | +----------------+
// Given two flows, one for handling positive ints and another // for handling negative ints, (both of type ContextFlow[Int, Int, Ctx]), // create a new flow that will handle positive ints with the postive flow // and negative ints with the negative flow. val flow: ContextFlow[Int, Int, Ctx] = MergeFlow( (positiveIntFlow, _ >= 0), (negativeIntFlow, _ < 0) )