Skip to content

Commit be51e0d

Browse files
authored
Add updated signal and dynamic workflow samples (#78)
1 parent 59acf75 commit be51e0d

File tree

4 files changed

+200
-2
lines changed

4 files changed

+200
-2
lines changed

new_samples/README.md

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ These are some samples to demonstrate various capabilities of Cadence client and
99
1. Run the Cadence server: https://github.com/uber/cadence/blob/master/README.md
1010
2. Register the `cadence-samples` domain: https://cadenceworkflow.io/docs/cli/#quick-start or https://github.com/uber/cadence/blob/master/tools/cli/README.md
1111

12-
12+
Detailed workflow histories can be viewed on Cadence UI. Go to `localhost:8088` on your browser for more details.
1313

1414
## Steps to run samples
1515
Simply start the go binary by running
@@ -30,4 +30,60 @@ cadence --env development \
3030
--et 60 \
3131
--input '{"message":"Uber"}'
3232
```
33-
Try to inspect the log message for the output.
33+
Try to inspect the log message for the output.
34+
35+
### Signal Workflow
36+
This workflow demonstrate a basic signal workflow. It takes your name as input parameter
37+
and greet you based on languages you pick. To start the workflow, try the following CLI.
38+
39+
```bash
40+
cadence --env development \
41+
--domain cadence-samples \
42+
workflow start \
43+
--workflow_type cadence_samples.SignalGreeterMultiLanguageWorkflow \
44+
--tl cadence-samples-worker \
45+
--et 6000 \
46+
--input '{"name":"Uber"}'
47+
```
48+
49+
A workflow ID and run ID will be return in your terminal. Copy the workflow ID and replace
50+
to the CLI below to trigger the signal. Try to change the input language value and inspect what
51+
happens in the log. Also, try to inspect what happened after you interact with the signal multiple times.
52+
53+
```bash
54+
cadence --env development \
55+
--domain cadence-samples \
56+
workflow signal \
57+
--workflow_id <Your workflow ID> \
58+
--name "language" \
59+
--input '"english"'
60+
```
61+
62+
To cancel the workflow, try the following CLI.
63+
64+
```bash
65+
cadence --env development \
66+
--domain cadence-samples \
67+
workflow signal \
68+
--workflow_id <Your workflow ID> \
69+
--name "cancel" \
70+
--input 'true'
71+
```
72+
The workflow should have a status of fail.
73+
74+
### Dynamic workflow
75+
This dynamic workflow is very similar to the Hello World workflow above, but instead of passing the
76+
function definition to the activity execution step, we can directly pass an activity name registered to the
77+
worker to run the workflow. Here is a sample CLI.
78+
79+
```bash
80+
cadence --env development \
81+
--domain cadence-samples \
82+
workflow start \
83+
--workflow_type cadence_samples.DynamicWorkflow \
84+
--tl cadence-samples-worker \
85+
--et 60 \
86+
--input '{"message":"Uber"}'
87+
```
88+
Try to inspect the log message for the output.
89+

new_samples/worker/worker.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ func StartWorker() {
4343
w.RegisterWorkflowWithOptions(workflows.HelloWorldWorkflow, workflow.RegisterOptions{Name: "cadence_samples.HelloWorldWorkflow"})
4444
w.RegisterActivityWithOptions(workflows.HelloWorldActivity, activity.RegisterOptions{Name: "cadence_samples.HelloWorldActivity"})
4545

46+
// Signal workflow registration
47+
w.RegisterWorkflowWithOptions(workflows.SignalGreeterMultiLanguageWorkflow, workflow.RegisterOptions{Name: "cadence_samples.SignalGreeterMultiLanguageWorkflow"})
48+
w.RegisterActivityWithOptions(workflows.GenerateGreetingMessage, activity.RegisterOptions{Name: "cadence_samples.GenerateGreetingMessage"})
49+
50+
// Dynamic workflow registration
51+
w.RegisterWorkflowWithOptions(workflows.DynamicWorkflow, workflow.RegisterOptions{Name: "cadence_samples.DynamicWorkflow"})
52+
w.RegisterActivityWithOptions(workflows.DynamicGreetingActivity, activity.RegisterOptions{Name: "cadence_samples.DynamicGreetingActivity"})
53+
4654
err := w.Start()
4755
if err != nil {
4856
panic("Failed to start worker: " + err.Error())
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package workflows
2+
3+
import (
4+
"context"
5+
"go.uber.org/cadence/activity"
6+
"go.uber.org/cadence/workflow"
7+
"go.uber.org/zap"
8+
"time"
9+
)
10+
11+
const DynamicGreetingActivityName = "cadence_samples.DynamicGreetingActivity"
12+
13+
type dynamicWorkflowInput struct {
14+
Message string `json:"message"`
15+
}
16+
17+
func DynamicWorkflow(ctx workflow.Context, input dynamicWorkflowInput) (string, error) {
18+
ao := workflow.ActivityOptions{
19+
ScheduleToStartTimeout: time.Minute,
20+
StartToCloseTimeout: time.Minute,
21+
}
22+
ctx = workflow.WithActivityOptions(ctx, ao)
23+
24+
logger := workflow.GetLogger(ctx)
25+
logger.Info("DynamicWorkflow started")
26+
27+
var greetingMsg string
28+
err := workflow.ExecuteActivity(ctx, DynamicGreetingActivityName, input.Message).Get(ctx, &greetingMsg)
29+
if err != nil {
30+
logger.Error("DynamicGreetingActivity failed", zap.Error(err))
31+
return "", err
32+
}
33+
34+
logger.Info("Workflow result", zap.String("greeting", greetingMsg))
35+
return greetingMsg, nil
36+
}
37+
38+
func DynamicGreetingActivity(ctx context.Context, message string) (string, error) {
39+
logger := activity.GetLogger(ctx)
40+
logger.Info("DynamicGreetingActivity started.")
41+
return "Hello, " + message, nil
42+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package workflows
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"go.uber.org/cadence/activity"
8+
"go.uber.org/cadence/workflow"
9+
"go.uber.org/zap"
10+
"time"
11+
)
12+
13+
// A workflow execution cannot receive infinite number of signals due to history limit
14+
// By default 10000 is MaximumSignalsPerExecution which can be configured by DynamicConfig of Cadence cluster.
15+
// But it's recommended to do continueAsNew after receiving certain number of signals(in production, use a number <1000)
16+
const (
17+
MaxSignalCount = 3
18+
19+
LanguageChan = "language"
20+
CancelChan = "cancel"
21+
)
22+
23+
type person struct {
24+
Name string `json:"name"`
25+
}
26+
27+
func SignalGreeterMultiLanguageWorkflow(ctx workflow.Context, person person) error {
28+
ao := workflow.ActivityOptions{
29+
ScheduleToStartTimeout: time.Minute * 60,
30+
StartToCloseTimeout: time.Minute * 60,
31+
}
32+
ctx = workflow.WithActivityOptions(ctx, ao)
33+
logger := workflow.GetLogger(ctx)
34+
logger.Info("SignalGreeterMultiLanguageWorkflow started, ", zap.String("Name", person.Name))
35+
36+
signalCount := 0
37+
38+
var language string
39+
var canceled bool
40+
languageChan := workflow.GetSignalChannel(ctx, LanguageChan)
41+
cancelChan := workflow.GetSignalChannel(ctx, CancelChan)
42+
for {
43+
s := workflow.NewSelector(ctx)
44+
s.AddReceive(languageChan, func(ch workflow.Channel, ok bool) {
45+
if ok {
46+
ch.Receive(ctx, &language)
47+
signalCount += 1
48+
}
49+
})
50+
51+
s.AddReceive(cancelChan, func(ch workflow.Channel, ok bool) {
52+
if ok {
53+
ch.Receive(ctx, &canceled)
54+
}
55+
})
56+
s.Select(ctx)
57+
58+
if canceled {
59+
return errors.New("signal workflow canceled")
60+
}
61+
if signalCount >= MaxSignalCount {
62+
return workflow.NewContinueAsNewError(ctx, SignalGreeterMultiLanguageWorkflow, person)
63+
}
64+
65+
var greeting string
66+
err := workflow.ExecuteActivity(ctx, GenerateGreetingMessage, language, person.Name).Get(ctx, &greeting)
67+
if err != nil {
68+
return err
69+
}
70+
71+
logger.Info("Greeting message", zap.String("Greeting", greeting))
72+
}
73+
}
74+
75+
func GenerateGreetingMessage(ctx context.Context, language, name string) (string, error) {
76+
logger := activity.GetLogger(ctx)
77+
logger.Info("GenerateGreetingMessage started")
78+
var greeting string
79+
if language == "english" {
80+
greeting = "Hello"
81+
}
82+
if language == "spanish" {
83+
greeting = "Hola"
84+
}
85+
if language == "french" {
86+
greeting = "bonjour"
87+
}
88+
if greeting == "" {
89+
return "", errors.New("currently only support english, spanish and french")
90+
}
91+
return fmt.Sprintf("%s %s!", greeting, name), nil
92+
}

0 commit comments

Comments
 (0)