> The problem right now is that there’s no way to control the behavior of the underlying Java threading libraries, nio, and writing to disk.

Nor will there ever be, just by the nature of those systems.

You can't get deterministic execution from a system that uses non-deterministic request ordering, task scheduling, etc. -- which is what you get if you always use multiple OS threads, or spawn multiple discrete processes in tests, and so on.

I mean, I guess you _can_ make that stuff deterministic, but it would require you to build synchronization points into every transition in your application state machines, in a way that would be controllable by tests, which is a very tall order!

In practice, the only way to do this kind of thing is to design the core of your system to be fully synchronous, and to make it concurrent by adding concurrency at higher layers, expressed at run-time.

never say never, i think maybe can be done with modifications to missionary, a structured concurrency dsl implementing process supervision for clojure/script. we already instrument missionary flows for testing missionary itself (asserting its state transitions)

I guess you're suggesting that you can build an abstraction layer (I guess you're calling it missionary) which (a) can reliably intermediate every interaction between a user program and any potentially non-deterministic API, and (b) can be configured at runtime as synchronous/serial/deterministic or async/concurrent/non-deterministic. Is this accurate? (If so, I'm pretty confident that this is infeasible.)

Electric Clojure backends already get such effect supervision for free (you'll need to manually tag sync/blocking effects). https://github.com/hyperfiddle/electric https://github.com/leonoel/missionary