Skip to content

Commit 0386dbd

Browse files
committed
Continued cleanup
1 parent 1555abe commit 0386dbd

6 files changed

Lines changed: 58 additions & 69 deletions

File tree

crates/sdk/src/workflows.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
pub use temporalio_workflow::workflows::*;
44

55
pub use crate::workflow_registry::WorkflowDefinitions;
6+
#[doc(inline)]
7+
pub use temporalio_macros::{workflow, workflow_methods};

crates/workflow/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ wit-bindgen = { version = "0.57.1", default-features = false, features = ["macro
3232
path = "../common-wasm"
3333
version = "0.2"
3434

35+
[dependencies.temporalio-macros]
36+
path = "../macros"
37+
version = "0.3"
38+
3539
[lints]
3640
workspace = true
37-
38-
[dev-dependencies]
39-
temporalio-macros = { path = "../macros" }

crates/workflow/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
extern crate self as temporalio_workflow;
66

77
pub use temporalio_common_wasm as common;
8+
pub use temporalio_macros::{
9+
init, query, run, signal, update, update_validator, workflow, workflow_methods,
10+
};
811

912
#[doc(hidden)]
1013
pub mod __private {

crates/workflow/wit/README.md

Lines changed: 45 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,58 @@
11
# Workflow Runtime WIT
22

3-
This directory defines the canonical high-level workflow guest interface for the future WASM SDK.
3+
This directory defines `temporal:workflow-runtime@0.1.0`, the high-level guest interface that
4+
workflow code targets when it is compiled to a WebAssembly component. It is intentionally separate
5+
from the core activation/completion protocol that worker SDKs speak to the Temporal cluster: core
6+
remains the worker-facing protocol, and a worker is responsible for translating core activations
7+
and completions into calls against this interface.
8+
9+
## What's in here
10+
11+
- `world.wit` — the `workflow-module` world: imports `workflow-host`, exports `workflow-guest`.
12+
- `guest.wit``workflow-guest`: the entry points the guest exports for the host to drive
13+
(`list-workflows`, `instantiate-workflow`, and the `workflow-instance` resource with `activate`
14+
and `poll-routine`).
15+
- `host.wit``workflow-host`: the host capabilities the guest imports (e.g. `set-current-details`,
16+
`push-command`).
17+
- `types.wit` — shared records and variants used by both sides (init/activation/completion shapes,
18+
routine kinds, terminal outcomes, etc.). Some fields are typed as `list<u8>` and carry encoded
19+
protobuf messages — those proto schemas are part of the ABI; see *Stability* below.
20+
21+
## How a workflow runs against it
22+
23+
1. The host instantiates a workflow run by calling `instantiate-workflow` with `workflow-init`.
24+
2. For each activation, the host calls `activate` on the `workflow-instance` resource. The guest
25+
processes the activation's jobs and reports per-job results (started routines, query responses,
26+
update rejections).
27+
3. The guest drives its routines (main, signals, updates) by being polled — the host calls
28+
`poll-routine(routine-id)` until the routine either completes or reports it made no progress.
29+
4. While running, the guest invokes host functions to push commands and update execution state.
30+
31+
The guest interface is deliberately higher-level than core's activation protocol: ordering rules
32+
and worker bookkeeping live in the host translation layer, not in the guest contract.
433

5-
This is intentionally **not** the existing core activation/completion protocol. Core remains the
6-
worker-facing protocol for the foreseeable future, and other language SDKs will continue to use it.
7-
The Rust worker will translate core activations and completions into this higher-level interface.
8-
9-
## Why this lives in `temporalio-workflow`
10-
11-
`temporalio-workflow` is the crate that workflow implementations compile against. Checking the WIT
12-
in here gives the Rust runtime refactor a concrete target:
13-
14-
- `temporalio_workflow::runtime::*` should evolve toward a direct Rust mirror of these interfaces.
15-
- The native Rust worker should keep calling those Rust traits directly, with no WIT serialization
16-
in the hot path.
17-
- A future WASM backend should expose the same interface through the component model.
18-
19-
## Layering
20-
21-
The layers are:
22-
23-
1. Core activation/completion protocol
24-
2. Native worker translation layer
25-
3. This WIT-shaped workflow runtime interface
26-
4. Workflow guest code
27-
28-
That translation layer is where activation ordering and other core-specific details stay hidden.
29-
The guest interface here is deliberately higher level:
30-
31-
- the host instantiates a workflow run
32-
- the host applies activation-wide context
33-
- the host notifies signals, cancellation, patches, updates, and operation resolutions
34-
- the guest polls until it blocks or terminates
34+
## Synchronous ABI and the WASIp3 future
3535

36-
## Native and WASM execution
36+
The guest interface is synchronous: `activate` and `poll-routine` return ordinary results, and a
37+
routine signals "blocked" by returning `routine-poll-result.made-progress = false`. The host
38+
re-enters `poll-routine` after the relevant activation lands. This shape is what stable Wasmtime
39+
and `wit-bindgen` support today.
3740

38-
The runtime should support two backends behind the same worker translation logic:
41+
When component-model async (WASIp3 / Preview 3) is stable in Wasmtime, the natural evolution is:
3942

40-
- a native backend that invokes Rust traits directly in-process
41-
- a WASM backend that invokes a component implementing `workflow-module`
43+
- `activate` and `poll-routine` become `async func`.
44+
- `routine-poll-result.made-progress` and the explicit `routine-id`-keyed polling protocol can
45+
go away — the host can `await` each routine directly.
4246

43-
The goal is one logical execution model with two transport backends, not two independent workers.
47+
That is a breaking ABI change and will require a major-version WIT bump.
4448

4549
## Stability
4650

47-
The package is published as `temporal:workflow-runtime@0.1.0` and is **not yet stable**. Until
48-
this is bumped to `1.0.0` any release may bump the minor version with breaking changes. Once
49-
external SDKs (Python, TypeScript, Go, etc.) begin compiling guest workflows against this WIT,
50-
breaking changes need to follow normal SemVer discipline: bump the package version, dual-export
51-
the old and new world from the host for a deprecation window, and document the migration path.
51+
The package is published as `temporal:workflow-runtime@0.1.0` and is **not yet stable**. Until it
52+
is bumped to `1.0.0`, any release may bump the minor version with breaking changes. Once external
53+
SDKs (Python, TypeScript, Go, etc.) begin compiling guest workflows against this WIT, breaking
54+
changes need to follow normal SemVer discipline: bump the package version, dual-export the old
55+
and new world from the host for a deprecation window, and document the migration path.
5256

5357
Changes that force a major bump include:
5458

@@ -57,21 +61,3 @@ Changes that force a major bump include:
5761
- Reordering variant cases (the discriminant order is part of the ABI).
5862
- Changing the proto messages encoded into `list<u8>`-typed fields (`failure`, `payload`,
5963
`workflow-command`, `workflow-activation`, `continue-as-new-request`).
60-
61-
## Synchronous ABI and the WASIp3 future
62-
63-
The current guest interface is intentionally synchronous: `activate` and `poll-routine` both
64-
return ordinary results, and the guest is expected to suspend by returning
65-
`routine-poll-result.made-progress = false`. The host then re-enters `poll-routine` after the
66-
relevant activation lands.
67-
68-
This shape is what stable Wasmtime + `wit-bindgen` support today. When component-model async
69-
(WASIp3 / Preview 3) lands as stable in Wasmtime, the natural evolution is:
70-
71-
- `activate` and `poll-routine` become `async func`.
72-
- `routine-poll-result.made-progress` and the explicit `routine-id`-keyed polling protocol
73-
likely go away — the host can just `await` each routine directly.
74-
75-
That is a breaking ABI change, so it will require a major-version WIT bump. Any other-language
76-
SDK that ships a guest implementation should expect to regenerate bindings against the new
77-
world at that point.

samples/wasm-workflows/hello/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ version = "0.1.0"
44
edition = "2024"
55

66
[dependencies]
7-
temporalio-macros = { path = "../../../crates/macros" }
87
temporalio-workflow = { path = "../../../crates/workflow" }
98

109
[lib]

samples/wasm-workflows/hello/src/lib.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use temporalio_macros::{workflow, workflow_methods};
2-
use temporalio_workflow::{WorkflowContext, WorkflowResult, export_workflow_module};
1+
use temporalio_workflow::{
2+
WorkflowContext, WorkflowResult, export_workflow_module, workflow, workflow_methods,
3+
};
34

45
#[workflow]
56
#[derive(Default)]
@@ -8,10 +9,7 @@ pub struct HelloWorkflow;
89
#[workflow_methods]
910
impl HelloWorkflow {
1011
#[run]
11-
pub async fn run(
12-
_ctx: &mut WorkflowContext<Self>,
13-
name: String,
14-
) -> WorkflowResult<String> {
12+
pub async fn run(_ctx: &mut WorkflowContext<Self>, name: String) -> WorkflowResult<String> {
1513
Ok(format!("Hello, {name}!"))
1614
}
1715
}

0 commit comments

Comments
 (0)