예제 #1
1
  // #timed
  // each time an event is pushed through it will trigger a period of silence
  public class TimedGate<A> extends GraphStage<FlowShape<A, A>> {

    private final FiniteDuration silencePeriod;

    public TimedGate(FiniteDuration silencePeriod) {
      this.silencePeriod = silencePeriod;
    }

    public final Inlet<A> in = Inlet.create("TimedGate.in");
    public final Outlet<A> out = Outlet.create("TimedGate.out");

    private final FlowShape<A, A> shape = FlowShape.of(in, out);

    @Override
    public FlowShape<A, A> shape() {
      return shape;
    }

    @Override
    public GraphStageLogic createLogic(Attributes inheritedAttributes) {
      return new TimerGraphStageLogic(shape) {

        private boolean open = false;

        {
          setHandler(
              in,
              new AbstractInHandler() {
                @Override
                public void onPush() {
                  A elem = grab(in);
                  if (open) pull(in);
                  else {
                    push(out, elem);
                    open = true;
                    scheduleOnce("key", silencePeriod);
                  }
                }
              });
          setHandler(
              out,
              new AbstractOutHandler() {
                @Override
                public void onPull() {
                  pull(in);
                }
              });
        }

        @Override
        public void onTimer(Object key) {
          if (key.equals("key")) {
            open = false;
          }
        }
      };
    }
  }
예제 #2
1
  // #materialized
  public class FirstValue<A>
      extends GraphStageWithMaterializedValue<FlowShape<A, A>, CompletionStage<A>> {

    public final Inlet<A> in = Inlet.create("FirstValue.in");
    public final Outlet<A> out = Outlet.create("FirstValue.out");

    private final FlowShape<A, A> shape = FlowShape.of(in, out);

    @Override
    public FlowShape<A, A> shape() {
      return shape;
    }

    @Override
    public Tuple2<GraphStageLogic, CompletionStage<A>> createLogicAndMaterializedValue(
        Attributes inheritedAttributes) {
      Promise<A> promise = Futures.promise();

      GraphStageLogic logic =
          new GraphStageLogic(shape) {
            {
              setHandler(
                  in,
                  new AbstractInHandler() {
                    @Override
                    public void onPush() {
                      A elem = grab(in);
                      promise.success(elem);
                      push(out, elem);

                      // replace handler with one just forwarding
                      setHandler(
                          in,
                          new AbstractInHandler() {
                            @Override
                            public void onPush() {
                              push(out, grab(in));
                            }
                          });
                    }
                  });

              setHandler(
                  out,
                  new AbstractOutHandler() {
                    @Override
                    public void onPull() {
                      pull(in);
                    }
                  });
            }
          };

      return new Tuple2(logic, promise.future());
    }
  }
예제 #3
0
  // #async-side-channel
  // will close upstream when the future completes
  public class KillSwitch<A> extends GraphStage<FlowShape<A, A>> {

    private final CompletionStage<Done> switchF;

    public KillSwitch(CompletionStage<Done> switchF) {
      this.switchF = switchF;
    }

    public final Inlet<A> in = Inlet.create("KillSwitch.in");
    public final Outlet<A> out = Outlet.create("KillSwitch.out");

    private final FlowShape<A, A> shape = FlowShape.of(in, out);

    @Override
    public FlowShape<A, A> shape() {
      return shape;
    }

    @Override
    public GraphStageLogic createLogic(Attributes inheritedAttributes) {
      return new GraphStageLogic(shape) {

        {
          setHandler(
              in,
              new AbstractInHandler() {
                @Override
                public void onPush() {
                  push(out, grab(in));
                }
              });
          setHandler(
              out,
              new AbstractOutHandler() {
                @Override
                public void onPull() {
                  pull(in);
                }
              });
        }

        @Override
        public void preStart() {
          AsyncCallback<Done> callback =
              createAsyncCallback(
                  new Procedure<Done>() {
                    @Override
                    public void apply(Done param) throws Exception {
                      completeStage();
                    }
                  });

          ExecutionContext ec = system.dispatcher();
          switchF.thenAccept(callback::invoke);
        }
      };
    }
  }
예제 #4
0
  // #one-to-many
  public class Duplicator<A> extends GraphStage<FlowShape<A, A>> {

    public final Inlet<A> in = Inlet.create("Duplicator.in");
    public final Outlet<A> out = Outlet.create("Duplicator.out");

    private final FlowShape<A, A> shape = FlowShape.of(in, out);

    @Override
    public FlowShape<A, A> shape() {
      return shape;
    }

    public GraphStageLogic createLogic(Attributes inheritedAttributes) {
      return new GraphStageLogic(shape) {
        // Again: note that all mutable state
        // MUST be inside the GraphStageLogic
        Option<A> lastElem = Option.none();

        {
          setHandler(
              in,
              new AbstractInHandler() {
                @Override
                public void onPush() {
                  A elem = grab(in);
                  lastElem = Option.some(elem);
                  push(out, elem);
                }

                @Override
                public void onUpstreamFinish() {
                  if (lastElem.isDefined()) {
                    emit(out, lastElem.get());
                  }
                  complete(out);
                }
              });

          setHandler(
              out,
              new AbstractOutHandler() {
                @Override
                public void onPull() {
                  if (lastElem.isDefined()) {
                    push(out, lastElem.get());
                    lastElem = Option.none();
                  } else {
                    pull(in);
                  }
                }
              });
        }
      };
    }
  }
예제 #5
0
  // #many-to-one
  public final class Filter<A> extends GraphStage<FlowShape<A, A>> {

    private final Predicate<A> p;

    public Filter(Predicate<A> p) {
      this.p = p;
    }

    public final Inlet<A> in = Inlet.create("Filter.in");
    public final Outlet<A> out = Outlet.create("Filter.out");

    private final FlowShape<A, A> shape = FlowShape.of(in, out);

    @Override
    public FlowShape<A, A> shape() {
      return shape;
    }

    public GraphStageLogic createLogic(Attributes inheritedAttributes) {
      return new GraphStageLogic(shape) {
        {
          setHandler(
              in,
              new AbstractInHandler() {
                @Override
                public void onPush() {
                  A elem = grab(in);
                  if (p.test(elem)) {
                    push(out, elem);
                  } else {
                    pull(in);
                  }
                }
              });

          setHandler(
              out,
              new AbstractOutHandler() {
                @Override
                public void onPull() {
                  pull(in);
                }
              });
        }
      };
    }
  }
예제 #6
0
  // #one-to-one
  public class Map<A, B> extends GraphStage<FlowShape<A, B>> {

    private final Function<A, B> f;

    public Map(Function<A, B> f) {
      this.f = f;
    }

    public final Inlet<A> in = Inlet.create("Map.in");
    public final Outlet<B> out = Outlet.create("Map.out");

    private final FlowShape<A, B> shape = FlowShape.of(in, out);

    @Override
    public FlowShape<A, B> shape() {
      return shape;
    }

    @Override
    public GraphStageLogic createLogic(Attributes inheritedAttributes) {
      return new GraphStageLogic(shape) {

        {
          setHandler(
              in,
              new AbstractInHandler() {
                @Override
                public void onPush() {
                  try {
                    push(out, f.apply(grab(in)));
                  } catch (Exception ex) {
                    failStage(ex);
                  }
                }
              });
          setHandler(
              out,
              new AbstractOutHandler() {
                @Override
                public void onPull() {
                  pull(in);
                }
              });
        }
      };
    }
  }
예제 #7
0
  // #simpler-one-to-many
  public class Duplicator2<A> extends GraphStage<FlowShape<A, A>> {

    public final Inlet<A> in = Inlet.create("Duplicator.in");
    public final Outlet<A> out = Outlet.create("Duplicator.out");

    private final FlowShape<A, A> shape = FlowShape.of(in, out);

    @Override
    public FlowShape<A, A> shape() {
      return shape;
    }

    @Override
    public GraphStageLogic createLogic(Attributes inheritedAttributes) {
      return new GraphStageLogic(shape) {

        {
          setHandler(
              in,
              new AbstractInHandler() {
                @Override
                public void onPush() {
                  A elem = grab(in);
                  // this will temporarily suspend this handler until the two elems
                  // are emitted and then reinstates it
                  emitMultiple(out, Arrays.asList(elem, elem).iterator());
                }
              });

          setHandler(
              out,
              new AbstractOutHandler() {
                @Override
                public void onPull() {
                  pull(in);
                }
              });
        }
      };
    }
  }
예제 #8
0
  // #simple-source
  public class NumbersSource extends GraphStage<SourceShape<Integer>> {
    // Define the (sole) output port of this stage
    public final Outlet<Integer> out = Outlet.create("NumbersSource.out");

    // Define the shape of this stage, which is SourceShape with the port we defined above
    private final SourceShape<Integer> shape = SourceShape.of(out);

    @Override
    public SourceShape<Integer> shape() {
      return shape;
    }

    // This is where the actual (possibly stateful) logic is created
    @Override
    public GraphStageLogic createLogic(Attributes inheritedAttributes) {
      return new GraphStageLogic(shape()) {
        // All state MUST be inside the GraphStageLogic,
        // never inside the enclosing GraphStage.
        // This state is safe to access and modify from all the
        // callbacks that are provided by GraphStageLogic and the
        // registered handlers.
        private int counter = 1;

        {
          setHandler(
              out,
              new AbstractOutHandler() {
                @Override
                public void onPull() {
                  push(out, counter);
                  counter += 1;
                }
              });
        }
      };
    }
  }
예제 #9
0
  // #detached
  public class TwoBuffer<A> extends GraphStage<FlowShape<A, A>> {

    public final Inlet<A> in = Inlet.create("TwoBuffer.in");
    public final Outlet<A> out = Outlet.create("TwoBuffer.out");

    private final FlowShape<A, A> shape = FlowShape.of(in, out);

    @Override
    public FlowShape<A, A> shape() {
      return shape;
    }

    @Override
    public GraphStageLogic createLogic(Attributes inheritedAttributes) {
      return new GraphStageLogic(shape) {

        private final int SIZE = 2;
        private Queue<A> buffer = new ArrayDeque<>(SIZE);
        private boolean downstreamWaiting = false;

        private boolean isBufferFull() {
          return buffer.size() == SIZE;
        }

        @Override
        public void preStart() {
          // a detached stage needs to start upstream demand
          // itself as it is not triggered by downstream demand
          pull(in);
        }

        {
          setHandler(
              in,
              new AbstractInHandler() {
                @Override
                public void onPush() {
                  A elem = grab(in);
                  buffer.add(elem);
                  if (downstreamWaiting) {
                    downstreamWaiting = false;
                    A bufferedElem = buffer.poll();
                    push(out, bufferedElem);
                  }
                  if (!isBufferFull()) {
                    pull(in);
                  }
                }

                @Override
                public void onUpstreamFinish() {
                  if (!buffer.isEmpty()) {
                    // emit the rest if possible
                    emitMultiple(out, buffer.iterator());
                  }
                  completeStage();
                }
              });

          setHandler(
              out,
              new AbstractOutHandler() {
                @Override
                public void onPull() {
                  if (buffer.isEmpty()) {
                    downstreamWaiting = true;
                  } else {
                    A elem = buffer.poll();
                    push(out, elem);
                  }
                  if (!isBufferFull() && !hasBeenPulled(in)) {
                    pull(in);
                  }
                }
              });
        }
      };
    }
  }