I’m trying to change the underlying dispatcher of FileIO. The docs say that it is using akka.stream. blocking-io-dispatcher. So I configured it like this:
Is the underlying file operation still done on my thread pool? Is logging just working on another thread pool? Something wrong with my assumptions or configuration?
How can I prove that the reading is done by my own thread pool?
val as = ActorSystem("test")
val settings = ActorMaterializerSettings(as)
val newSettings = settings.withDispatcher("my-dispatcher")
val mat = ActorMaterializer(newSettings)(as)
FileIO
.fromPath(Paths.get("/tmp/toto.txt"))
.fold(ByteString.empty)(_ ++ _)
.map(_ => println(s"Current thread: ${Thread.currentThread().getName}"))
.runWith(Sink.ignore)(mat)
First of: Thanks for the answer. I would have used it as is if I would not be using. Akka 2.6. But the thing that actually triggered the solve was this line
I did not think of doing that. When I added it I saw that my stream was working correctly. But it got me back on reading the documentation.
Turns out I had some misconceptions:
Since the logging is done asynchronously the thread in which the logging was performed is captured in Mapped Diagnostic Context (MDC) with attribute name sourceThread.
Of course it makes sense that the logging takes place on another thread and does not block the original thread.
To write the actual thread that initiated the logging you have to use [%X{sourceThread}] in your logbook configuration. A [%thread] would just print out the logging thread which is normally not really helpful (for me).
Bit I still have some Problems:
On top of that, I am using Akka 2.6. That means that ActorMaterializerSettings and ActorMaterializer is deprecated.
The custom dispatcher is set on the fromPath operator only, while the log and fold operators are on the default dispatcher. When the dispatcher attribute changes between operators it leads to an asynchronous boundary, so the fromPath will run in one actor and the log + fold in another.
If you want to run more operators in the same dispatcher, you’d have to move the attribute down:
Thanks for pointing that out. That was something I actually tripped over after making my realizations and did not address in my post above.
I went through the scenarios you are describing - there were a log statements after each operator in my code until I made the realization that you would (normally) want the withDispatcher as close to the run as possible (for simple flows- where you would maybe want only one async boundary).