简体   繁体   中英

How do I extract the real-time FileIO state from Akka?

I am making a file transfer system using Akka. I've been looking at the documents for a while. The current status of progress is Actor2 received the file sent by Actor1 and wrote it to the local system of Actor2 (Actor1 = sender, Actor2 = receiver).

But I couldn't find a way to know how much byte I received in real time when writing.

I tested it, and it turns out, with runWith API, files can be written locally. With runForeach API, how much byte was delivered in real time through. However, if these two are created at the same time, the file cannot be written.

Here's my simple source. Please give me some advice.

public static Behavior<Command> create() {
    return Behaviors.setup(context -> {
        context.getLog().info("Registering myself with receptionist");
        context.getSystem().receptionist().tell(Receptionist.register(RECEIVER_SERVICE_KEY, context.getSelf().narrow()));
        Materializer mat = Materializer.createMaterializer(context);

        return Behaviors.receive(Command.class)
                .onMessage(TransferFile.class, command -> {
                    command.sourceRef.getSource().runWith(FileIO.toPath(Paths.get("test.pptx")), mat);
                    //command.replyTo.tell(new FileTransfered("filename", 1024));
                    command.sourceRef.getSource().runForeach(f -> System.out.println(f.size()), mat);
                    return Behaviors.same();
                }).build();
    });
}

Use a BroadcastHub to allow multiple consumers of your Source :

Source<ByteString, NotUsed> fileSource = command.sourceRef.getSource();

RunnableGraph<Source<ByteString, NotUsed>> runnableGraph =
  fileSource.toMat(BroadcastHub.of(ByteString.class, 256), Keep.right());
// adjust the buffer size (256) as needed

Source<ByteString, NotUsed> fromFileSource = runnableGraph.run(mat);

fromFileSource.runWith(FileIO.toPath(Paths.get("test.pptx")), mat);
fromFileSource.runForeach(f -> System.out.println(f.size()), mat);

BroadcastHub as suggested by Jeffrey, allows for a single running stream to be connected to multiple other streams that are started and stopped over time.

Having a stream that dynamically connects to others requires quite a lot of extra hoops internally, so if you don't need that it is better to avoid that overhead.

If you use case is rather that you want to consume a single source with two sinks that is better done with source.alsoTo(sink1).to(sink2) .

alsoTo in the flow API is backed by the Broadcast operator, but using that directly requires that you use the Graph DSL.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM