Usually two methods `onMessage(long timeNow, byte[] buf)` and `onTimer(long timeNow, int timerId)`.
All output sinks and a scheduler need to be passed in on construction of the application.
Then you can record all inputs to a file. Outputs don’t need to be recorded because the inputs can be replayed but it is useful for easier analysis when bugs happen.
I have even worked on systems where there were tools that you could paste recorded input and outputs to and they code generated the source code for a unit test. Super useful for reproducing issues quickly.
But you are spot on in that there is an overhead. For example, if you want to open a TCP socket and then read and write to it, you need to create a separate service and serialise all the inputs and outputs in a way that can be recorded and replayed.
Interesting approach. I often get to the same goal by using the replicated state machine pattern. Where all inputs to a system are recorded. Both methods seem to rely on designing your application in a very specific way to be able to replay inputs and deterministically get the same outputs.
Usually two methods `onMessage(long timeNow, byte[] buf)` and `onTimer(long timeNow, int timerId)`.
All output sinks and a scheduler need to be passed in on construction of the application.
Then you can record all inputs to a file. Outputs don’t need to be recorded because the inputs can be replayed but it is useful for easier analysis when bugs happen.
I have even worked on systems where there were tools that you could paste recorded input and outputs to and they code generated the source code for a unit test. Super useful for reproducing issues quickly.
But you are spot on in that there is an overhead. For example, if you want to open a TCP socket and then read and write to it, you need to create a separate service and serialise all the inputs and outputs in a way that can be recorded and replayed.