Effect-TS / effect

An ecosystem of tools to build robust applications in TypeScript

Home Page:https://effect.website

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature Request: Virtual time scheduler

dilame opened this issue · comments

What is the problem this feature would solve?

In RxJS, I often use the VirtualTimeScheduler to test algorithms on historical data by simulating real-time data streams. This feature allows for a seamless transition between real-time and historical data testing without changing the core logic of the application.

I noticed that effect currently lacks a similar functionality in its Scheduler concept. The ability to virtualize time would be extremely beneficial for developers like me who need to test their reactive systems more thoroughly by controlling the flow of time in tests.

What is the feature you are proposing to solve the problem?

I would like to request the addition of a VirtualTimeScheduler in effect. This scheduler would ideally allow:

  • Simulating the passage of time, enabling deterministic and controlled testing environments.
  • Testing time-sensitive operations without real delays, thus speeding up the test suite.
  • Flexibility to interoperate with existing Scheduler functionalities for seamless integration.

This also comes as part of our TestContext (https://github.com/Effect-TS/effect/blob/661004f4bf5f8b25f5a0678c21a3a822188ce461/packages/effect/src/TestContext.ts) which is also utilized by our @effect/vitest package.

Closing this for now. Feel free to re-open if this didn't answer your question!

It is almost the same, but actually, not:) RxJS VirtualTimeScheduler automatically tracks the time, while Effect TestClock requires user to manually adjust time.

VirtualTimeScheduler doesn't even have any methods to manually set time. The only method it offers is VirtualTimeScheduler.flush() which execute all of its queued actions and takes care of adjusting time. It is crucial when you have multiple parallel processes, each with different delays, and each of them wants to know the current time at different points of executions.

Something like this. I know, it looks non realistic, but it's just a simple simulation of real world scenarios

const waitRandomTimeAndPrintCurrentTime = Effect.gen(function *(){
    const randomSleepTime = yield* Random.nextIntBetween(1000,5000);
    yield* Effect.sleep(randomSleepTime);
    const currentTime = yield* Clock.currentTimeMillis;
    yield* Console.log(currentTime);
})

const test = Effect.gen(function* () {

    yield* Effect.forkDaemon(waitRandomTimeAndPrintCurrentTime)
    yield* Effect.forkDaemon(waitRandomTimeAndPrintCurrentTime)

})

I would like to have something like TestClock.flush that will execute all the actions that are waiting for execution. Something like tick in event loop, but for fibers.