https://github.com/lbovet/reactive-plumber
Groovy DSL for declarative Reactor or RxJava streaming graphs
https://github.com/lbovet/reactive-plumber
Last synced: 13 days ago
JSON representation
Groovy DSL for declarative Reactor or RxJava streaming graphs
- Host: GitHub
- URL: https://github.com/lbovet/reactive-plumber
- Owner: lbovet
- License: apache-2.0
- Created: 2017-01-28T17:33:04.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2022-07-18T12:08:44.000Z (almost 3 years ago)
- Last Synced: 2025-04-15T21:48:24.248Z (13 days ago)
- Language: Java
- Homepage:
- Size: 198 KB
- Stars: 5
- Watchers: 2
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Reactive Plumber
[](https://travis-ci.org/lbovet/reactive-plumber?branch=master)
[](https://gitter.im/reactive-plumber/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)A swisspush project
You want to use [Reactor](https://projectreactor.io/) (or [RxJava](https://github.com/ReactiveX/RxJava)) within a modular, readable and safe abstraction.
Reactive-Plumber let you write your reactive stream plumbing in a Groovy DSL and also visualize it graphically.
It is intended to be used in Java or Groovy applications.
```groovy
def data = pipe {
from input map wrap
}def printer = {
from it doOnNext print
}def renderer = pipe {
parallel from(data) \
map renderThread
}def count = pipe {
from data count()
}def size = pipe {
from data \
zipWith value(count), attach \
map renderSize \
compose printer
}def thread = pipe {
from renderer compose printer
}drain size, thread
```Built using these outstanding projects:
- [Groovy](http://groovy-lang.org)
- [RxJava](https://github.com/ReactiveX/RxJava)
- [Project Reactor](https://projectreactor.io)
- [graphviz-java](https://github.com/nidi3/graphviz-java)
## The DSLHave a look at the [examples scripts](https://github.com/lbovet/reactive-plumber/tree/master/reactive-plumber-test/src/main/resources/examples).
### Pipes
The idea is to write the pipelines in Groovy, using parenthese-less method chaining.
So a simple definition of a pipe could be:
```groovy
def items = pipe {
just 1, 2, 3 \
map Integer.&bitCount \
map String.&valueOf
}
```This defines a _pipe_, which is actually a Reactor _Flux_ (or RxJava _Flowable_). In the closure block, we simply chain existing stream methods. Here we count the bits in each numbers and convert them into strings.
### From
To connect pipes together, use _from_:
```groovy
def printer = pipe {
from items \
to { x -> print x }
}
```### Drain
It is not sufficient to connect pipes together in order to define your plumbing. You also need to declare on which pipes are terminal to ensure that all events are processed.
```groovy
drain printer
```### Tools
You will expose your own functions to be used in the plumbing. Do that in a sub-class of `Plumbing`, so that when you import statically your functions, you will also get the Reactive-Plumber builtin functions.
_Tools.groovy_:
```groovy
import Plumbingabstract class Tools extends Plumbing {
static input = Domain.&input
static print = Domain.&print
static renderThread = Domain.&renderThread
static renderSize = Domain.&renderSize
}
```_script.groovy_:
```groovy
import static Tools.*;
```### Pipe Functions
The builtin pipe functions are
| *Function* | *Description* |
| ------------------|-----------------------------|
| `pipe` | Declares a pipe. |
| `from` | Connects this pipe's input to a previously declared pipe. |
| `drain` | Declare a pipe as terminal. |
| `split` | Returns an array of pipes filtered with a predicate array. |
| `concurrent` | Processes this pipe concurrently to other pipes. |
| `parallel` | Processes the events in this pipe in parallel. |
| `value` | Provide the result of a pipe in form suitable to be combine with other pipe items, usually via `zipWith`. |You can also dynamically create pipes. This uses _GroupedFlowable_ under the hood:
| *Function* | *Description* |
| ------------------|-----------------------------|
| `groups` | Return a pipe of pipes grouped by a grouping function. |
| `key` | Extracts the key of a grouped pipe. |
| `each` | Declares a pipe to apply to each grouped pipe outputed by `groups` |### Box Functions
This library provides a monadic wrapper type _Box_ that allows to transport context along with values throughout pipes. If you use it in your pipes, you may want to import the following functions to your Tools class.
| *Function* | *Description* |
| ------------------|-----------------------------|
| wrap | Creates a box around a value. |
| unwrap | Removes the box and returns the value. |
| attach | Add a context to a box. |
| mapper | Applies a function to a value inside a box. |
| bind | Flat-maps the box, apply a function on the value returning a box. |
| context | Add a context to the box using the grouping key of grouped pipes. |## Examples
Each example has a pipeline Groovy script and an adapter Java class that exposes the business logic methods in a simple static functional form.
### One
[one.groovy](https://github.com/lbovet/reactive-plumber/tree/master/reactive-plumber-test/src/main/resources/examples/one/one.groovy)
[One.java](https://github.com/lbovet/reactive-plumber/blob/master/reactive-plumber-test/src/main/java/examples/one/One.java)
output:
```
[1 [RxComputationThreadPool-1]|]
[1 / 4|]
[2 [RxComputationThreadPool-2]|]
[2 / 4|]
[3 [RxComputationThreadPool-3]|]
[4 [RxComputationThreadPool-4]|]
[3 / 4|]
[4 / 4|].
```### Two
[two.groovy](https://github.com/lbovet/reactive-plumber/tree/master/reactive-plumber-test/src/main/resources/examples/two/two.groovy)
[Two.java](https://github.com/lbovet/reactive-plumber/blob/master/reactive-plumber-test/src/main/java/examples/two/Two.java)
output:
```
2 EVEN
3 ODD.
```### Three
[three.groovy](https://github.com/lbovet/reactive-plumber/tree/master/reactive-plumber-test/src/main/resources/examples/three/three.groovy)
[Three.java](https://github.com/lbovet/reactive-plumber/blob/master/reactive-plumber-test/src/main/java/examples/three/Three.java)
output:
```
1
2
FIZZ
4
BUZZ
FIZZ
7
8
FIZZ
BUZZ
11
FIZZ
13
14
FIZZBUZZ
FIZZ: 4
BUZZ: 2
FIZZBUZZ: 1.
```### Five
[five.groovy](https://github.com/lbovet/reactive-plumber/tree/master/reactive-plumber-test/src/main/resources/examples/five/five.groovy)
[Five.java](https://github.com/lbovet/reactive-plumber/blob/master/reactive-plumber-test/src/main/java/examples/five/Five.java)
output:
```
strings, [hello|], [world|]
numbers, [5|], [3|].
```## Graph Visualization
Reactive-Plumber can create graph images of your plumbing like the ones above by analyzing the Groovy AST of the script.
```java
Runtime runtime = new Runtime().withGraphTheme(Runtime.GraphTheme.LIGHT); // White background
runtime.generateGraph("src/main/resources/examples/one/one.groovy", new File("target/graph.png"));
runtime.generateGraph("src/main/resources/examples/one/one.groovy", "svg", System.out));
```