Interface Pipeline

  • All Known Implementing Classes:
    DefaultPipeline, DrasylPipeline, EmbeddedPipeline

    public interface Pipeline
    A list of Handlers which handles or intercepts inbound events and outbound operations of a DrasylNode. Pipeline implements an advanced form of the Intercepting Filter pattern to give a user full control over how an event is handled and how the Handlers in a pipeline interact with each other. This implementation is very closely based on the netty implementation.

    Creation of a pipeline

    Each per DrasylNode exists one pipeline and it is created automatically when a new node is created.

    How an event flows in a pipeline

    The following diagram describes how I/O events are processed by Handlers in a Pipeline typically. An I/O event are handled by a Handler and be forwarded to its closest handler by calling the event propagation methods defined in HandlerContext, such as HandlerContext.fireRead(Address, Object, CompletableFuture) and HandlerContext.write(Address, Object, CompletableFuture) .

                                                     I/O Request
                                                via HandlerContext
                                                          |
      +---------------------------------------------------+---------------+
      |                            Pipeline               |               |
      |                                                  \|/              |
      |    +---------------------+            +-----------+----------+    |
      |    |      Handler  N     |            |       Handler  1     |    |
      |    +----------+----------+            +-----------+----------+    |
      |              /|\                                  |               |
      |               |                                  \|/              |
      |    +----------+----------+            +-----------+----------+    |
      |    |      Handler N-1    |            |       Handler  2     |    |
      |    +----------+----------+            +-----------+----------+    |
      |              /|\                                  .               |
      |               .                                   .               |
      |   HandlerContext.fireIN_EVT()          HandlerContext.OUT_EVT()   |
      |        [method call]                        [method call]         |
      |               .                                   .               |
      |               .                                  \|/              |
      |    +----------+----------+            +-----------+----------+    |
      |    |      Handler  2     |            |       Handler M-1    |    |
      |    +----------+----------+            +-----------+----------+    |
      |              /|\                                  |               |
      |               |                                  \|/              |
      |    +----------+----------+            +-----------+----------+    |
      |    |      Handler  1     |            |       Handler  M     |    |
      |    +----------+----------+            +-----------+----------+    |
      |              /|\                                  |               |
      +---------------+-----------------------------------+---------------+
                      |                                  \|/
      +---------------+-----------------------------------+---------------+
      |               |                                   |               |
      |   [ DrasylNodeComponent ]              [ MessageSink.send() ]     |
      |                                                                   |
      |  drasyl internal I/O                                              |
      +-------------------------------------------------------------------+
      

    An inbound event is handled by the handlers in the bottom-up direction as shown on the left side of the diagram. A handler usually handles the inbound data generated by the I/O thread on the bottom of the diagram. The inbound data is often read from a remote peer via the actual input operation. If an inbound event goes beyond the top handler, it is passed to the application.

    An outbound event is handled by the handler in the top-down direction as shown on the right side of the diagram. A handler usually generates or transforms the outbound traffic such as write requests.

    For example, let us assume that we created the following pipeline:

     Pipeline p = ...;
     p.addLast("1", new HandlerA());
     p.addLast("2", new HandlerB());
     p.addLast("3", new HandlerC());
     p.addLast("4", new HandlerD());
     p.addLast("5", new HandlerE());
     
    In the given example configuration, the handler evaluation order is 1, 2, 3, 4, 5 when an event goes inbound. When an event goes outbound, the order is 5, 4, 3, 2, 1.

    Forwarding an event to the next handler

    As you might noticed in the diagram, a handler has to invoke the event propagation methods in HandlerContext to forward an event to its next handler. Those methods include:

    Thread safety

    A Handler can be added or removed at any time because a Pipeline is thread safe.

  • But for every invocation of:
  • the invocation is scheduled in the DrasylScheduler, therefore the order of invocations can't be guaranteed. You have to ensure by yourself, that your handlers are thread-safe if you need it. Also, you have to ensure the order of messages, if you need it.