Skip to content

Commit b86320d

Browse files
authored
Workflow to demonstrate workflow.sleep for 30 seconds (#99)
* Workflow to demostrate Sleep for 30 seconds
1 parent 6350c61 commit b86320d

File tree

5 files changed

+213
-0
lines changed

5 files changed

+213
-0
lines changed

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ PROGS = helloworld \
3535
pageflow \
3636
signalcounter \
3737
sideeffect \
38+
sleep \
3839

3940
TEST_ARG ?= -race -v -timeout 5m
4041
BUILD := ./build
@@ -68,6 +69,7 @@ TEST_DIRS=./cmd/samples/cron \
6869
./cmd/samples/recipes/searchattributes \
6970
./cmd/samples/recipes/sideeffect \
7071
./cmd/samples/recipes/signalcounter \
72+
./cmd/samples/recipes/sleep \
7173
./cmd/samples/recovery \
7274
./cmd/samples/pso \
7375

@@ -81,6 +83,9 @@ helloworld:
8183
delaystart:
8284
go build -o bin/delaystart cmd/samples/recipes/delaystart/*.go
8385

86+
sleep:
87+
go build -o bin/sleep cmd/samples/recipes/sleep/*.go
88+
8489
branch:
8590
go build -o bin/branch cmd/samples/recipes/branch/*.go
8691

@@ -207,6 +212,7 @@ bins: helloworld \
207212
pageflow \
208213
signalcounter \
209214
sideeffect \
215+
sleep \
210216

211217
test: bins
212218
@rm -f test
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Sleep Workflow Sample
2+
3+
This sample workflow demonstrates how to use the `workflow.Sleep` function in Cadence workflows. The sleep functionality allows workflows to pause execution for a specified duration before continuing with subsequent activities.
4+
5+
## Sample Description
6+
7+
The sample workflow:
8+
- Takes a sleep duration as input parameter
9+
- Uses `workflow.Sleep` to pause workflow execution for the specified duration
10+
- Executes a main activity after the sleep period completes
11+
- Demonstrates proper error handling for sleep operations
12+
- Shows how to configure activity options for post-sleep activities
13+
14+
The workflow is useful for scenarios where you need to:
15+
- Implement delays or timeouts in workflow logic
16+
- Wait for external events or conditions
17+
- Implement retry mechanisms with exponential backoff
18+
- Create scheduled or periodic workflows
19+
20+
## Key Components
21+
22+
- **Workflow**: `sleepWorkflow` demonstrates the sleep functionality with activity execution
23+
- **Activity**: `mainSleepActivity` is executed after the sleep period
24+
- **Sleep Duration**: Configurable duration (default: 30 seconds) passed as workflow input
25+
- **Test**: Includes unit tests to verify sleep and activity execution
26+
27+
## Steps to Run Sample
28+
29+
1. You need a cadence service running. See details in cmd/samples/README.md
30+
31+
2. Run the following command to start the worker:
32+
```
33+
./bin/sleep -m worker
34+
```
35+
36+
3. Run the following command to execute the workflow:
37+
```
38+
./bin/sleep -m trigger
39+
```
40+
41+
You should see logs showing:
42+
- Workflow start with sleep duration
43+
- Sleep completion message
44+
- Main activity execution
45+
- Workflow completion
46+
47+
## Customization
48+
49+
To modify the sleep behavior:
50+
- Change the `sleepDuration` in `main.go` to adjust the default sleep time
51+
- Modify the activity options to configure timeouts for post-sleep activities
52+
- Add additional activities or logic after the sleep period
53+
- Implement conditional sleep based on workflow state
54+
55+
## Use Cases
56+
57+
This pattern is useful for:
58+
- **Scheduled Tasks**: Implement workflows that need to wait before processing
59+
- **Rate Limiting**: Add delays between API calls or external service interactions
60+
- **Retry Logic**: Implement exponential backoff for failed operations
61+
- **Event-Driven Workflows**: Wait for specific time periods before checking conditions
62+
- **Batch Processing**: Add delays between batch operations to avoid overwhelming systems

cmd/samples/recipes/sleep/main.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"time"
6+
7+
"github.com/pborman/uuid"
8+
"go.uber.org/cadence/client"
9+
"go.uber.org/cadence/worker"
10+
11+
"github.com/uber-common/cadence-samples/cmd/samples/common"
12+
)
13+
14+
const (
15+
ApplicationName = "sleepTaskList"
16+
SleepWorkflowName = "sleepWorkflow"
17+
)
18+
19+
func startWorkers(h *common.SampleHelper) {
20+
workerOptions := worker.Options{
21+
MetricsScope: h.WorkerMetricScope,
22+
Logger: h.Logger,
23+
FeatureFlags: client.FeatureFlags{
24+
WorkflowExecutionAlreadyCompletedErrorEnabled: true,
25+
},
26+
}
27+
h.StartWorkers(h.Config.DomainName, ApplicationName, workerOptions)
28+
}
29+
30+
func startWorkflow(h *common.SampleHelper) {
31+
sleepDuration := 30 * time.Second
32+
workflowOptions := client.StartWorkflowOptions{
33+
ID: "sleep_" + uuid.New(),
34+
TaskList: ApplicationName,
35+
ExecutionStartToCloseTimeout: time.Minute,
36+
DecisionTaskStartToCloseTimeout: time.Minute,
37+
}
38+
h.StartWorkflow(workflowOptions, SleepWorkflowName, sleepDuration)
39+
}
40+
41+
func registerWorkflowAndActivity(h *common.SampleHelper) {
42+
h.RegisterWorkflowWithAlias(sleepWorkflow, SleepWorkflowName)
43+
h.RegisterActivity(mainSleepActivity)
44+
}
45+
46+
func main() {
47+
var mode string
48+
flag.StringVar(&mode, "m", "trigger", "Mode is worker or trigger.")
49+
flag.Parse()
50+
51+
var h common.SampleHelper
52+
h.SetupServiceConfig()
53+
54+
switch mode {
55+
case "worker":
56+
registerWorkflowAndActivity(&h)
57+
startWorkers(&h)
58+
select {}
59+
case "trigger":
60+
startWorkflow(&h)
61+
}
62+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"time"
6+
7+
"go.uber.org/cadence/activity"
8+
"go.uber.org/cadence/workflow"
9+
"go.uber.org/zap"
10+
)
11+
12+
const sleepWorkflowName = "sleepWorkflow"
13+
14+
// sleepWorkflow demonstrates workflow.Sleep followed by a main activity call
15+
func sleepWorkflow(ctx workflow.Context, sleepDuration time.Duration) error {
16+
logger := workflow.GetLogger(ctx)
17+
logger.Info("Workflow started, will sleep", zap.String("duration", sleepDuration.String()))
18+
19+
// Sleep for the specified duration
20+
err := workflow.Sleep(ctx, sleepDuration)
21+
if err != nil {
22+
logger.Error("Sleep failed", zap.Error(err))
23+
return err
24+
}
25+
26+
logger.Info("Sleep finished, executing main activity")
27+
28+
// Set activity options
29+
activityOptions := workflow.ActivityOptions{
30+
ScheduleToStartTimeout: time.Minute,
31+
StartToCloseTimeout: time.Minute,
32+
HeartbeatTimeout: time.Second * 20,
33+
}
34+
ctx = workflow.WithActivityOptions(ctx, activityOptions)
35+
36+
var result string
37+
err = workflow.ExecuteActivity(ctx, mainSleepActivity).Get(ctx, &result)
38+
if err != nil {
39+
logger.Error("Main activity failed", zap.Error(err))
40+
return err
41+
}
42+
43+
logger.Info("Workflow completed", zap.String("Result", result))
44+
return nil
45+
}
46+
47+
// mainSleepActivity is a simple activity for demonstration
48+
func mainSleepActivity(ctx context.Context) (string, error) {
49+
logger := activity.GetLogger(ctx)
50+
logger.Info("mainSleepActivity executed")
51+
return "Main sleep activity completed", nil
52+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package main
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/stretchr/testify/require"
8+
"go.uber.org/cadence/activity"
9+
"go.uber.org/cadence/encoded"
10+
"go.uber.org/cadence/testsuite"
11+
)
12+
13+
func Test_Sleep(t *testing.T) {
14+
testSuite := &testsuite.WorkflowTestSuite{}
15+
16+
env := testSuite.NewTestWorkflowEnvironment()
17+
env.RegisterWorkflow(sleepWorkflow)
18+
env.RegisterActivity(mainSleepActivity)
19+
20+
var activityMessage string
21+
env.SetOnActivityCompletedListener(func(activityInfo *activity.Info, result encoded.Value, err error) {
22+
result.Get(&activityMessage)
23+
})
24+
25+
sleepDuration := 5 * time.Second
26+
env.ExecuteWorkflow(sleepWorkflow, sleepDuration)
27+
28+
require.True(t, env.IsWorkflowCompleted())
29+
require.NoError(t, env.GetWorkflowError())
30+
require.Equal(t, "Main sleep activity completed", activityMessage)
31+
}

0 commit comments

Comments
 (0)