In-Memory Runtimes
Both in-memory runtimes store workflow state in memory without persistence. They differ in their concurrency model:
| Synchronized | Concurrent | |
|---|---|---|
| Module | workflows4s-core | workflows4s-cats-effect |
| Effect requirements | MonadThrow | Async (cats-effect) |
| Under contention | Blocks thread | Suspends fiber |
| On cancellation | Lock may leak | Releases lock cleanly |
| Best for | Tests, simple/synchronous usage | Concurrent/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")