Might be interesting for avoiding vendor lock-in or simplify migration.
Idea
Run a WIO program inside a Temporal workflow. A new WorkflowRuntime registers a worker whose workflow function interprets the WIO AST, translating each node to a Temporal primitive. Temporal owns durability, scheduling, and signal delivery; workflows4s contributes the DSL and the declarative rendering.
High-level shape
The interpreter that already exists is pure Scala over the AST and takes now: Instant as input. Plugging it into Temporal means:
- A
TemporalRuntime implementing WorkflowRuntime, with a worker that hosts the workflow function.
- The workflow function walks the WIO and dispatches to Temporal APIs for the few effectful nodes.
- Time is injected via the existing clock seam (
BasicEngine.now) using Temporal's deterministic clock.
- The wakeup scheduler (
KnockerUpper) is unused — Temporal's own sleep/await supersedes it.
Node mapping
(Approximate, to be verified)
RunIO → activity invocation
Timer (static or dynamic) → Workflow.sleep
AwaitingTime → Workflow.sleep until target instant
HandleSignal → Temporal signal channel
Parallel → Async.function / promise composition
Pure / Transform / Fork / Loop / AndThen / FlatMap → in-workflow control flow (the interpreter already handles these)
HandleError / HandleErrorWith → exceptions in the interpreter
Retry → loop in the interpreter
Embedded → recursive interpretation of the inner WIO
End → workflow returns
Tradeoffs accepted
- Event-sourced model collapses — Temporal's history is the durable record. The workflows4s event log is unused for this backend, and constructs that lean on it (
Checkpoint, Recovery) need a deliberate mapping or are dropped.
- Activity payloads need codecs.
- The whole interpreter must stay deterministic on replay, which it already is modulo
RunIO bodies — those run as activities outside workflow context, so non-determinism there is fine.
Open questions for the prototype
- Activity identity for
RunIO — each node needs a stable name so Temporal history can dispatch on replay.
- AST evolution under replay — when a WIO definition changes while instances are in flight, history may no longer line up. Need a versioning story (Temporal's
getVersion, or an AST-level identity scheme).
- Retry coordination —
WIO.Retry vs Temporal's activity-level retry policy. Probably let the WIO drive and disable Temporal's retry, but worth confirming.
Checkpoint / Recovery — map onto Temporal's history / continueAsNew, or drop for v1.
Might be interesting for avoiding vendor lock-in or simplify migration.
Idea
Run a
WIOprogram inside a Temporal workflow. A newWorkflowRuntimeregisters a worker whose workflow function interprets the WIO AST, translating each node to a Temporal primitive. Temporal owns durability, scheduling, and signal delivery; workflows4s contributes the DSL and the declarative rendering.High-level shape
The interpreter that already exists is pure Scala over the AST and takes
now: Instantas input. Plugging it into Temporal means:TemporalRuntimeimplementingWorkflowRuntime, with a worker that hosts the workflow function.BasicEngine.now) using Temporal's deterministic clock.KnockerUpper) is unused — Temporal's ownsleep/awaitsupersedes it.Node mapping
(Approximate, to be verified)
RunIO→ activity invocationTimer(static or dynamic) →Workflow.sleepAwaitingTime→Workflow.sleepuntil target instantHandleSignal→ Temporal signal channelParallel→Async.function/ promise compositionPure/Transform/Fork/Loop/AndThen/FlatMap→ in-workflow control flow (the interpreter already handles these)HandleError/HandleErrorWith→ exceptions in the interpreterRetry→ loop in the interpreterEmbedded→ recursive interpretation of the inner WIOEnd→ workflow returnsTradeoffs accepted
Checkpoint,Recovery) need a deliberate mapping or are dropped.RunIObodies — those run as activities outside workflow context, so non-determinism there is fine.Open questions for the prototype
RunIO— each node needs a stable name so Temporal history can dispatch on replay.getVersion, or an AST-level identity scheme).WIO.Retryvs Temporal's activity-level retry policy. Probably let the WIO drive and disable Temporal's retry, but worth confirming.Checkpoint/Recovery— map onto Temporal's history /continueAsNew, or drop for v1.