-
Notifications
You must be signed in to change notification settings - Fork 8
Add documentation for ctx.awaitEvent and ctx.runWorkflow features #174
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
Add documentation for ctx.awaitEvent and ctx.runWorkflow features #174
Conversation
Co-Authored-By: Ian Macartney <ian@convex.dev>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the ✨ Finishing touches🧪 Generate unit tests (beta)
Comment |
commit: |
README.md
Outdated
| To send the event from elsewhere (e.g., after a user clicks a button): | ||
|
|
||
| ```ts | ||
| import { vWorkflowId, WorkflowManager } from "@convex-dev/workflow"; |
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.
both this and the above code snippet don't include the workflow variable, and import WorkflowManager but don't use it.
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.
Fixed! I've added the workflow variable creation and necessary imports to the code snippets:
- First snippet now shows
const workflow = new WorkflowManager(components.workflow)and importscomponents, internal - Second snippet now imports
mutationfrom_generated/serverand has a comment noting thatworkflowandapprovalEventare defined above - Third snippet (awaiting by ID) also now shows the full setup with
workflowcreation
Co-Authored-By: Ian Macartney <ian@convex.dev>
Co-Authored-By: Ian Macartney <ian@convex.dev>
Co-Authored-By: Ian Macartney <ian@convex.dev>
|
@Nicolapps would this have sufficed for you? |
Nicolapps
left a comment
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.
Thank you!
README.md
Outdated
|
|
||
| ```ts | ||
| const approvalEvent = defineEvent({ | ||
| name: "approval", |
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.
I’m a little bit confused by what’s going on here:
- Why are we using
"approval"here and notv.literal("approval")? - Why are you using
"approval" as constin the example but not here?
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.
These are great questions about the API design! I documented the current API behavior based on the existing implementation in src/client/index.ts and the example files. The name field is a plain string (not a validator) because defineEvent just returns the spec object as-is for spreading. The as const in the example file is for TypeScript type narrowing but isn't strictly required.
I'll defer to @ianmacartney on whether the API design should be changed or if the documentation should explain the rationale for these choices.
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.
Good catch - the as const was necessary before defineEvent, which captures the literal value.
It isn't a validator, as we need a single concrete value. When we await an event, we register what we're waiting for by the name. So a validator would imply we could pass a union of literals or a string etc.
README.md
Outdated
| const approval = await ctx.awaitEvent(approvalEvent); | ||
|
|
||
| // From a mutation: | ||
| await workflow.sendEvent(ctx, { ...approvalEvent, workflowId, value }); |
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 line looks confusing to me. Why does the API want you to spread the return value of defineEvent? Instead of having something like:
await workflow.sendEvent(ctx, { event: approvalEvent, workflowId, value: { approved: true } });Also, the code example here doesn’t show what value is.
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.
Good point about the value not being shown! The spread syntax is how the current API works - defineEvent returns { name, validator } which gets spread into the sendEvent call along with workflowId and value.
I can update the example to show the actual value being passed:
await workflow.sendEvent(ctx, { ...approvalEvent, workflowId, value: { approved: true } });The API design question about whether it should use { event: approvalEvent } instead of spreading is a good one for @ianmacartney to weigh in on.
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.
Great question, and it was something I went back & forth on in the design quite a bit. Essentially defineEvent is a convenience over passing in the name and validator directly.
You can call workflow.sendEvent(ctx, { name, workflowId }) or workflow.sendEvent(ctx, { id: eventId }), and spreading helps keep the types simpler - where the validator and value match in the same generic.
Co-Authored-By: Ian Macartney <ian@convex.dev>
Co-Authored-By: Ian Macartney <ian@convex.dev>
Summary
Adds documentation for two workflow context features that were previously undocumented:
ctx.awaitEvent: Explains how workflows can pause and wait for external events. Documents basic usage first (awaiting by name or by ID), then introducesdefineEventas a separate concept for sharing event names and validators between workflow and sender.ctx.runWorkflow: Explains how to run nested workflows as a single step, including scheduling options.The documentation uses focused code snippets and links to example files for complete, compilable implementations.
Updates since last revision
as constto thedefineEventexample name field for proper type inference (per reviewer feedback)value: { approved: true }in thesendEventexample to show actual usagectx.awaitEventsection: basic usage (by name/ID) is explained first, thendefineEventis introduced separatelyexample/convex/passingSignals.tsfor event ID patterns andexample/convex/userConfirmation.tsfordefineEventusageReview & Testing Checklist for Human
as constusage in thedefineEventexample is correct and matches the actual API requirementsNotes
Co-Authored-By: Ian Macartney ian@convex.dev