-
Notifications
You must be signed in to change notification settings - Fork 64
docs(temporal) WB-529 submission test plan #131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jimmeryn
wants to merge
3
commits into
main
Choose a base branch
from
docs/WB-529-submission-test-plan
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # Testing | ||
|
|
||
| The tested unit is the plugin. That is `WorkflowBuilderPlugin`, the three Activities it registers, and the workflow-side code that its `./workflow` entry point runs in Temporal's V8 sandbox. The three Activities are `executeNode`, `emitEvent` and `updateStatus`. | ||
|
|
||
| The reference backend and worker in `apps/` are sample consumers of the plugin. What a node executor does is consumer code. No test covers the full path from HTTP request to database write. | ||
|
|
||
| ```bash | ||
| pnpm --filter @workflowbuilder/temporal test | ||
| pnpm --filter @workflowbuilder/temporal typecheck # gates the contract check below | ||
| pnpm --filter @workflow-builder/execution-core test | ||
| ``` | ||
|
|
||
| No Docker, no Temporal cluster, no API key and no database. The replay suite starts a dev server binary. `@temporalio/testing` downloads that binary into the system temp directory, and downloads it again when the cached copy is more than one day old. The suite therefore needs network access on a clean machine, and on every CI runner. | ||
|
|
||
| ## Replay safety | ||
|
|
||
| **Deterministic sandbox code.** [`replay-audit.md`](../execution-core/replay-audit.md) gives a verdict for each reviewed source of non-determinism. It also lists the rules that new sandbox code must follow. [`graph-runner.replay-determinism.test.ts`](../execution-core/src/graph-runner.replay-determinism.test.ts) enforces this. It runs each graph shape several times against the same deterministic mocks, then compares the sequence of port calls. The sequences must be identical. The test needs no server and completes in milliseconds. | ||
|
|
||
| **A real run.** [`test/replay/replay.test.ts`](test/replay/replay.test.ts) runs a graph on a real Temporal dev server. It uses Temporal's own bundler, a real `Worker`, and the plugin's three Activities. The store and the node executors are test fixtures. The test counts the scheduled Activities of each type. It expects one `executeNode` per node, one `emitEvent` per emitted event, and one `updateStatus`. Then it runs the same graph with the workflow cache off and expects the same counts. `maxCachedWorkflows: 0` turns the cache off. Every workflow task then replays from the first event instead of continuing from a cached state. A side effect that repeats on replay changes one of the counts. | ||
|
|
||
| **A history recorded by older code.** The test replays [`histories/v0-parallel-wave.json`](test/replay/histories/) against the current code. This check fails when the current code would issue a command that the recorded run never made. A Workflow Execution can wait for days, so this check is what makes it safe to change the package between releases. [`test/replay/README.md`](test/replay/README.md) describes how to record a history, and what to do when this check fails. The correct response is different before and after the first release. | ||
|
|
||
| **Where the guarantee stops.** Replay does not run an Activity again if Temporal recorded its result. A retry does run it again. The plugin schedules one Activity per node, on a profile that allows two attempts, so a node executor must accept that it can run more than once. `emitEvent` and `updateStatus` run on a profile that allows five attempts. The workflow assigns each event its own `sequence` number, so a store can make that write idempotent. The reference worker does this with `ON CONFLICT (execution_id, sequence) DO NOTHING`. No test covers that write. | ||
|
|
||
| ## Limitations | ||
|
|
||
| - **Cancellation is untested.** No test runs the cancellation branch in `run-workflow.ts`. | ||
| - **Node failure is untested in the sandbox.** The fixture executors in the replay test never fail. The failure branch of the workflow therefore runs only in the `execution-core` tests, and in the Activity tests. | ||
| - **Only one history is recorded.** It covers the parallel-wave shape. No other graph shape has a cross-version check. | ||
| - **No CI job tests against the newest `@temporalio/*`.** Every job installs the pinned versions. A regression in the SDK therefore appears when someone upgrades, not on a pull request. | ||
| - **Temporal's `patched()` is not called anywhere.** There are two documented responses to a change in the emitted command sequence. You can put the new behaviour behind `patched()`, or you can release a major version and drain the runs that are in flight first. Because no `patched()` call exists, draining is the response available today. See [`README.md`](README.md) § "Versioning and replay". | ||
|
|
||
| ## What the suites pin | ||
|
|
||
| | Suite | Pins | Gated by | | ||
| | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | | ||
| | [`test/replay/`](test/replay/) | The replay checks in the replay safety section above | `test` | | ||
| | [`test/bundling.test.ts`](test/bundling.test.ts) | That the `./workflow` entry loads in the sandbox. Temporal's bundler rejects a worker-side or client-side import, so such an import fails here instead of in a consumer's worker | `test` | | ||
| | [`test/activities.test.ts`](test/activities.test.ts) | Executor dispatch, and which failures Temporal may retry. A permanent error becomes a non-retryable `ApplicationFailure`. Also plugin construction: the plugin's Activities do not displace the consumer's, the name stays `workflowbuilder.WorkflowBuilderPlugin`, a bad activity profile fails `Worker.create` instead of the first workflow activation, and a profile with no matching executor writes a warning | `test` | | ||
| | [`test/api-surface.test.ts`](test/api-surface.test.ts) | The exact runtime exports of all three entry points, and the values of the default profiles. Types are absent on purpose. The last row covers the exports map | `test` | | ||
| | [`src/workflow/profile-validation.test.ts`](src/workflow/profile-validation.test.ts) | Which activity profiles are accepted and which are rejected. A profile is copied at the boundary, so a later change to the caller's map has no effect. The profile keys that have no matching executor are named | `test` | | ||
| | [`src/workflow/node-activity-options.test.ts`](src/workflow/node-activity-options.test.ts) | Timeout, retry and Summary resolution for each node type, the fallback when a type has no profile, and safe handling of a node type named like an `Object.prototype` key | `test` | | ||
| | [`src/workflow/sequenced-event-emitter.test.ts`](src/workflow/sequenced-event-emitter.test.ts) | Event numbering and write order, driven through the real `runGraph`. Rows must become visible in ascending `sequence` order, or the SSE cursor in the reference backend skips one. One failed write must not drop the rest of the run | `test` | | ||
| | [`test/core-contract.test.ts`](test/core-contract.test.ts) | That the types this package restates match `execution-core`. It checks assignability in both directions, so adding or removing a field breaks the build. The assertions are at type level only | `typecheck` | | ||
| | [`execution-core`](../execution-core/) | The graph runner itself: topological scheduling, error policy, start-node resolution, template resolution, redaction and error classification | `test` | | ||
| | The published package | `publint` and `arethetypeswrong` check the package as it would publish. Three subpaths with their own types is where an exports map breaks without warning | CI only | | ||
|
|
||
| [`pr-check.yml`](../../.github/workflows/pr-check.yml) runs these in two jobs. The `temporal` job covers this package. The `execution` job covers `execution-core` and the reference apps. Both jobs trigger only on pull requests into `main`, so they do not gate a `release/*` pull request. [`release-temporal.yml`](../../.github/workflows/release-temporal.yml) runs the same sequence again on the release tag, before it publishes. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will become deprecated once WB-629 is finished 😊