You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> **PipelinR** is a lightweight command processing pipeline ❍ ⇢ ❍ ⇢ ❍ for your awesome Java app.
10
9
11
-
PipelinR has been battle-proven on production as a service layer for some cool FinTech apps. PipelinR has helped teams switch from giant service classes handling all use cases to small handlers, each following the single responsibility principle. It's similar to a popular [MediatR](https://github.com/jbogard/MediatR) .NET library.
10
+
PipelinR has been battle-proven on production as a service layer for some serious FinTech apps. PipelinR has helped teams switch from giant service classes handling all use cases to small handlers, following the single responsibility principle. It's similar to a popular [MediatR](https://github.com/jbogard/MediatR) .NET library.
12
11
13
12
⚡ Tested and works with plain Java, Kotlin, Spring, and Jakarta EE.
14
13
15
14
## Table of contents
15
+
16
16
-[How to use](#how-to-use)
17
17
-[Commands](#commands)
18
18
-[Handlers](#handlers)
@@ -50,11 +50,10 @@ Java version required: 1.8+.
50
50
51
51
## Commands
52
52
53
-
**Commands** is a request that can return a value. The `Ping` command below returns a string:
53
+
**Commands** is a request that can return a value. The following `Ping` command returns a string:
54
54
55
55
```java
56
56
classPingimplementsCommand<String> {
57
-
58
57
publicfinalString host;
59
58
60
59
publicPing(Stringhost) {
@@ -63,11 +62,10 @@ class Ping implements Command<String> {
63
62
}
64
63
```
65
64
66
-
If a command has nothing to return, you can use a built-in `Voidy` return type:
65
+
If a command has nothing to return, use a built-in `Voidy` return type:
67
66
68
67
```java
69
68
classPingimplementsCommand<Voidy> {
70
-
71
69
publicfinalString host;
72
70
73
71
publicPing(Stringhost) {
@@ -84,7 +82,6 @@ Create a handler by implementing `Command.Handler<C, R>` interface, where `C` is
@@ -93,16 +90,13 @@ class Pong implements Command.Handler<Ping, String> {
93
90
```
94
91
95
92
## Pipeline
93
+
96
94
A **pipeline** mediates between commands and handlers. You send commands to the pipeline. When the pipeline receives a command, it sends the command through a sequence of middlewares and finally invokes the matching command handler. `Pipelinr` is a default implementation of `Pipeline` interface.
97
95
98
96
To construct a `Pipeline`, create an instance of `Pipelinr` and provide a list of command handlers:
@@ -117,19 +111,26 @@ since v0.4, you can execute commands more naturally:
117
111
newPing("localhost").execute(pipeline);
118
112
```
119
113
120
-
`Pipelinr` can receive an optional, **ordered list** of custom middlewares. Every command will go through the middlewares before being handled. Use middlewares when you want to add extra behavior to command handlers, such as validation, logging, transactions, or metrics:
114
+
`Pipelinr` can receive an optional, **ordered list** of middlewares. Every command will go through the middlewares before being handled. Use middlewares to add extra behavior to command handlers, such as validation, logging, transactions, or metrics:
By default, command handlers are being resolved using generics. By overriding command handler's `matches` method, you can dynamically select a matching handler:
171
+
By default, command handlers are resolved using generics. By overriding command handler's `matches` method, you can dynamically select a matching handler:
@@ -269,19 +246,22 @@ new Pipelinr().with(() -> Stream.of(new Transactional()))
269
246
```
270
247
271
248
### Notification handling strategies
249
+
272
250
The default implementation loops through the notification handlers and awaits each one. This ensures each handler is run after one another.
273
251
274
252
Depending on your use-case for sending notifications, you might need a different strategy for handling the notifications, such running handlers in parallel.
275
253
276
254
PipelinR supports the following strategies:
277
-
*`an.awesome.pipelinr.StopOnException` runs each notification handler after one another; returns when all handlers are finished or an exception has been thrown; in case of an exception, any handlers after that will not be run; **this is a default strategy**.
278
-
*`an.awesome.pipelinr.ContinueOnException` runs each notification handler after one another; returns when all handlers are finished; in case of any exception(s), they will be captured in an AggregateException.
279
-
*`an.awesome.pipelinr.Async` runs all notification handlers asynchronously; returns when all handlers are finished; in case of any exception(s), they will be captured in an AggregateException.
280
-
*`an.awesome.pipelinr.ParallelNoWait` runs each notification handler in a thread pool; returns immediately and does not wait for any handlers to finish; cannot capture any exceptions.
281
-
*`an.awesome.pipelinr.ParallelWhenAny` runs each notification handler in a thread pool; returns when any thread (handler) is finished; all exceptions that happened before returning are captured in an AggregateException.
282
-
*`an.awesome.pipelinr.ParallelWhenAll` runs each notification handler in a thread pool; returns when all threads (handlers) are finished; in case of any exception(s), they are captured in an AggregateException.
255
+
256
+
-`an.awesome.pipelinr.StopOnException` runs each notification handler after one another; returns when all handlers are finished or an exception has been thrown; in case of an exception, any handlers after that will not be run; **this is a default strategy**.
257
+
-`an.awesome.pipelinr.ContinueOnException` runs each notification handler after one another; returns when all handlers are finished; in case of any exception(s), they will be captured in an AggregateException.
258
+
-`an.awesome.pipelinr.Async` runs all notification handlers asynchronously; returns when all handlers are finished; in case of any exception(s), they will be captured in an AggregateException.
259
+
-`an.awesome.pipelinr.ParallelNoWait` runs each notification handler in a thread pool; returns immediately and does not wait for any handlers to finish; cannot capture any exceptions.
260
+
-`an.awesome.pipelinr.ParallelWhenAny` runs each notification handler in a thread pool; returns when any thread (handler) is finished; all exceptions that happened before returning are captured in an AggregateException.
261
+
-`an.awesome.pipelinr.ParallelWhenAll` runs each notification handler in a thread pool; returns when all threads (handlers) are finished; in case of any exception(s), they are captured in an AggregateException.
283
262
284
263
You can override default strategy via:
264
+
285
265
```java
286
266
newPipelinr().with(newContinueOnException());
287
267
```
@@ -290,27 +270,25 @@ new Pipelinr().with(new ContinueOnException());
290
270
291
271
PipelinR works well with Spring and Spring Boot.
292
272
293
-
Start by configuring a `Pipeline`. Create an instance of `Pipelinr` and inject all command handlers and **ordered** middlewares via the constructor:
273
+
Start by configuring a `Pipeline`. Create an instance of `Pipelinr` and inject all command handlers and **ordered** middlewares:
0 commit comments