如何使用MergeHub w / Flow.mapAsync()

时间:2017-09-07 01:24:04

标签: java akka-stream

我对如何使用MergeHub感到困惑。

我正在设计一个使用Flow.mapAsync()的流程图,其中给定的函数创建另一个流程图,然后使用Sink.ignore()运行它,并返回CompletionStage作为Flow.mapAsync()要等待的值。嵌套流将通过实现Sink返回的MergeHub返回元素。

问题在于,当我创建顶级流程图时,我需要提供Function来启动嵌套流程到Flow.mapAsync(),但这需要它可以访问从实现MergeHub.of()的结果返回的具体化值。如何在启动流程图之前获得该物化值?

我现在能看到的唯一方法是实现Function阻止,直到提供Sink(在启动顶级流程图之后),但这看起来很糟糕。< / p>

所以,像

class MapAsyncFunctor implements Function<T, CompletionStage<Done>> {...}
MapAsyncFunctor mapAsyncFunctor = new MapAsyncFunctor();
RunnableGraph<Sink<T>> graph = createGraph(mapAsyncFunctor);
Sink<T> sink = materializer.materialize(graph);
mapAsyncFunctor.setSink(sink); // Graph execution blocked in background in call to mapAsyncFunctor.apply() until this is done

编辑:我已创建以下课程

public final class Channel<T>
{
    private final Sink<T, NotUsed> m_channelIn;
    private final Source<T, NotUsed> m_channelOut;
    private final UniqueKillSwitch m_killSwitch;

    public Channel(Class<T> in_class, Materializer in_materializer)
    {
        final Source<T, Sink<T, NotUsed>> source = MergeHub.of(in_class);
        final Sink<T, Source<T, NotUsed>> sink = BroadcastHub.of(in_class);

        final Pair<Pair<Sink<T, NotUsed>, UniqueKillSwitch>, Source<T, NotUsed>> matVals = in_materializer.materialize(source.viaMat(KillSwitches.single(), Keep.both()).toMat(sink, Keep.both()));

        m_channelIn = matVals.first().first();
        m_channelOut = matVals.second();
        m_killSwitch = matVals.first().second();
    }

    public Sink<T, NotUsed> in()
    {
        return m_channelIn;
    }

    public Source<T, NotUsed> out()
    {
        return m_channelOut;
    }

    public void close()
    {
        m_killSwitch.shutdown();
    }
}

这样我就可以使用Source / Sink对来构建图形。这是一个好主意吗?我是否会泄漏&#39;这些渠道如果我没有明确关闭() 它们?

我只需要为我的用例使用.out()一次。

1 个答案:

答案 0 :(得分:1)

使用MergeHub 始终需要在执行任何其他操作之前实现集线器接收器。

Sink<T, NotUsed> toConsumer = MergeHub.of(String.class, 16).to(consumer).run(materializer);

然后,您可以将其分发到需要实现它以向其发送数据的所有代码位。按照上面的代码段,可能的方法可能是在构建时通过Sink您的仿函数:

class MapAsyncFunctor implements Function<T, CompletionStage<Done>> {

    private Sink<T, NotUsed> sink;

    public MapAsyncFunctor(Sink<T, NotUsed> sink) {
        this.sink = sink;
    }

    @Override
    public CompletionStage<Done> apply(T t) { /* run substream into sink */ }
}

MapAsyncFunctor mapAsyncFunctor = new MapAsyncFunctor(toConsumer);

// run your flow with mapAsync on the above functor

MergeHub的更多信息可以在docs找到。