Skip to content

Commit 2b3be9b

Browse files
btraversclaude
andcommitted
feat(examples)!: port to the v8 split API and demonstrate signals, queries, errors, and schedules
Port the order-processing example to the TypedClient/ContractClient split (TypedClient.create({ client }).get() + .for(contract), synchronous getHandle, qualifyFailure) and extend it across the advertised surface: an approval signal + payload-less defineSignal() cancellation, an argument-less defineQuery({ output }) status query, a PaymentDeclined typed contract error travelling activity -> workflow -> client (matched with P.tag), and a schedule-driven activity-less cleanupExpiredOrders workflow with the ScheduleAlreadyExistsError create-if-absent idiom. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 8f77082 commit 2b3be9b

18 files changed

Lines changed: 1002 additions & 380 deletions

File tree

examples/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66

77
### [order-processing-contract](./order-processing-contract)
88

9-
Shared contract package — domain schemas and the workflow/activity definitions imported by both the worker and the client
9+
Shared contract package — domain schemas plus the workflow, activity, signal, query, and typed-error definitions imported by both the worker and the client (composition-first with the `define*` helpers)
1010

1111
### [order-processing-worker](./order-processing-worker)
1212

13-
Worker with Clean Architecture; activities return `AsyncResult` from unthrown
13+
Worker with Clean Architecture; activities return `AsyncResult` from unthrown, the workflow handles signals/queries via `context.defineSignal`/`defineQuery`, and a schedule-driven cleanup workflow shows the activity-less workflow shape
1414

1515
### [order-processing-client](./order-processing-client)
1616

17-
Standalone client demonstrating interaction with the shared contract
17+
Standalone client demonstrating the `TypedClient.create({ client }).for(contract)` split: typed signals (with and without payload), an argument-less query, a typed `PaymentDeclined` contract error matched with `P.tag`, and a recurring schedule with the create-if-absent idiom
1818

1919
**Note**: The client example works with the worker implementation seamlessly through the shared contract (`orderProcessingContract`).
2020

examples/order-processing-client/README.md

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,19 @@ This sample demonstrates that a single client can interact with any worker imple
66

77
## Overview
88

9-
This client package demonstrates that:
10-
11-
- The `order-processing-worker` implements the **unified contract**
12-
- The client works with the worker implementation through the shared contract
13-
- Workers handle errors internally using the Result/Future pattern with ApplicationFailure
9+
This client package demonstrates:
10+
11+
- The `TypedClient.create({ client })` (connection-scoped root) +
12+
`.for(contract)` (contract-scoped client) split
13+
- Typed signals through the workflow handle — `approveOrder` with a validated
14+
payload, and the payload-less `cancelRequested` sent with no arguments
15+
- An argument-less query (`getOrderStatus`) reading live workflow state
16+
- The synchronous `getHandle`, returning a `Result` whose only Err is
17+
`WorkflowNotInContractError`
18+
- A typed contract error (`PaymentDeclined`) rehydrated from a failed
19+
execution and matched exhaustively with unthrown's `match` + `P.tag`
20+
- A recurring cleanup schedule via `schedule.create(...)`, with the
21+
`ScheduleAlreadyExistsError` branch implementing the create-if-absent idiom
1422

1523
## Running the Sample
1624

@@ -47,17 +55,15 @@ pnpm dev
4755

4856
## Testing
4957

50-
The client includes integration tests that verify:
51-
52-
- Workflow execution through the contract
53-
- Proper input validation via contract schema
54-
- Correct output types matching contract schema
55-
- Workflow history and metadata access
56-
57-
Run tests:
58+
Integration tests live in the worker package
59+
(`../order-processing-worker/src/integration.spec.ts`) and cover the same
60+
surface this client demonstrates — start/execute, the approval signal + status
61+
query, the payload-less cancellation signal, input validation, and the typed
62+
`PaymentDeclined` contract error:
5863

5964
```bash
60-
pnpm test
65+
cd ../order-processing-worker
66+
pnpm test:integration # requires Docker (testcontainers)
6167
```
6268

6369
## What to Notice
@@ -73,15 +79,21 @@ pnpm test
7379

7480
The unified contract (`orderProcessingContract`) defines:
7581

76-
- Global activities: `log`, `sendNotification`
82+
- Global activities: `sendNotification`, `purgeExpiredOrders`
7783
- Workflow: `processOrder`
78-
- Activities: `processPayment`, `reserveInventory`, `releaseInventory`, `createShipment`, `refundPayment`
84+
- Activities: `processPayment` (with the `PaymentDeclined` typed error), `reserveInventory`, `releaseInventory`, `createShipment`, `refundPayment`
85+
- Signals: `approveOrder` (payload), `cancelRequested` (payload-less)
86+
- Query: `getOrderStatus` (argument-less)
87+
- Errors: `PaymentDeclined`
88+
- Workflow: `cleanupExpiredOrders` (activity-less; started by the schedule)
7989

8090
### Worker Implementation
8191

8292
The worker (`examples/order-processing-worker`) uses `@temporal-contract/worker` with:
8393

84-
- Activities using the Result/Future pattern with ApplicationFailure
94+
- Activities returning unthrown `AsyncResult` values (never throwing), with
95+
`ApplicationFailure` for technical faults and typed constructors for
96+
contract errors
8597
- Clean Architecture with dependency injection
8698
- Standalone TypeScript application
8799

0 commit comments

Comments
 (0)