Skip to main content

In-Memory Runtimes

Both in-memory runtimes store workflow state in memory without persistence. They differ in their concurrency model:

SynchronizedConcurrent
Moduleworkflows4s-coreworkflows4s-cats-effect
Effect requirementsMonadThrowAsync (cats-effect)
Under contentionBlocks threadSuspends fiber
On cancellationLock may leakReleases lock cleanly
Best forTests, simple/synchronous usageConcurrent/async usage with fibers

Concurrent Runtime

The concurrent runtime is built on top of cats-effect and uses functional concurrency primitives (Ref, Semaphore). It is fiber-safe and cancellation-safe.

Example

import MyWorkflowCtx.*
val workflow: WIO.Initial = ???
val engine: WorkflowInstanceEngine[IO, Ctx] = ???
val runtime: InMemoryConcurrentRuntime[IO, Ctx] = InMemoryConcurrentRuntime
.default(workflow, InitialState(), engine)
.unsafeRunSync()
val wfInstance: IO[InMemoryConcurrentWorkflowInstance[IO, Ctx]] = runtime.createInstance("my-workflow-1")

Synchronized Runtime

The synchronized runtime uses JVM-level synchronization primitives. It is thread-safe but not fiber-safe — under contention it blocks the carrier thread rather than suspending the fiber.

Example

import MyWorkflowCtx.*
val workflow: WIO.Initial = ???
val engine: WorkflowInstanceEngine[Try, Ctx] = ???
val runtime: InMemorySynchronizedRuntime[Try, Ctx] = InMemorySynchronizedRuntime.create(workflow, InitialState(), engine)
val wfInstance: Try[InMemorySynchronizedWorkflowInstance[Try, Ctx]] = runtime.createInstance("my-workflow-1")