69 lines
2.0 KiB
Markdown
69 lines
2.0 KiB
Markdown
---
|
|
title: Follow Workflow Constraints
|
|
impact: CRITICAL
|
|
impactDescription: Violating constraints breaks recovery and durability guarantees
|
|
tags: workflow, constraints, rules, best-practices
|
|
---
|
|
|
|
## Follow Workflow Constraints
|
|
|
|
Workflows have specific constraints to maintain durability guarantees. Violating them can break recovery.
|
|
|
|
**Incorrect (starting workflows from steps):**
|
|
|
|
```go
|
|
func myStep(ctx context.Context) (string, error) {
|
|
// Don't start workflows from steps!
|
|
// The step's context.Context does not support workflow operations
|
|
return "", nil
|
|
}
|
|
|
|
func myWorkflow(ctx dbos.DBOSContext, input string) (string, error) {
|
|
// Starting a child workflow inside a step breaks determinism
|
|
dbos.RunAsStep(ctx, func(ctx context.Context) (string, error) {
|
|
handle, _ := dbos.RunWorkflow(ctx.(dbos.DBOSContext), otherWorkflow, "data") // WRONG
|
|
return handle.GetWorkflowID(), nil
|
|
})
|
|
return "", nil
|
|
}
|
|
```
|
|
|
|
**Correct (workflow operations only from workflows):**
|
|
|
|
```go
|
|
func fetchData(ctx context.Context) (string, error) {
|
|
// Steps only do external operations
|
|
resp, err := http.Get("https://api.example.com")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
body, _ := io.ReadAll(resp.Body)
|
|
return string(body), nil
|
|
}
|
|
|
|
func myWorkflow(ctx dbos.DBOSContext, input string) (string, error) {
|
|
data, err := dbos.RunAsStep(ctx, fetchData, dbos.WithStepName("fetchData"))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
// Start child workflows from the parent workflow
|
|
handle, err := dbos.RunWorkflow(ctx, otherWorkflow, data)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
// Receive messages from the workflow
|
|
msg, err := dbos.Recvstring
|
|
// Set events from the workflow
|
|
dbos.SetEvent(ctx, "status", "done")
|
|
return data, nil
|
|
}
|
|
```
|
|
|
|
Additional constraints:
|
|
- Don't modify global variables from workflows or steps
|
|
- All workflows and queues must be registered **before** `Launch()`
|
|
- Concurrent steps must start in deterministic order using `dbos.Go`/`dbos.Select`
|
|
|
|
Reference: [Workflow Guarantees](https://docs.dbos.dev/golang/tutorials/workflow-tutorial#workflow-guarantees)
|