Skip to content

Commit 4f4d6ef

Browse files
authoredFeb 6, 2025··
Add sleep-for-days sample (#384)
* sleep-for-days sample * add test, fixed bugs
1 parent e0cc741 commit 4f4d6ef

File tree

5 files changed

+157
-0
lines changed

5 files changed

+157
-0
lines changed
 

‎sleep-for-days/README.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
### Sleep for days
2+
3+
This sample demonstrates how to create a Temporal workflow that runs forever, sending an email every 30 days.
4+
5+
### Steps to run this sample:
6+
1) Run a [Temporal service](https://github.com/temporalio/samples-go/tree/main/#how-to-use).
7+
2) Run the following command to start the worker
8+
```
9+
go run worker/main.go
10+
```
11+
3) Run the following command to start the example
12+
```
13+
go run starter/main.go
14+
```
15+
16+
This sample will run indefinitely until you send a `complete` signal to the workflow. See how to send a signal via Temporal CLI [here](https://docs.temporal.io/cli/workflow#signal).
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package sleepfordays
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
"go.temporal.io/sdk/activity"
9+
"go.temporal.io/sdk/workflow"
10+
)
11+
12+
func SleepForDaysWorkflow(ctx workflow.Context) (string, error) {
13+
ctx = workflow.WithActivityOptions(ctx, workflow.ActivityOptions{
14+
StartToCloseTimeout: 10 * time.Second,
15+
})
16+
17+
isComplete := false
18+
sigChan := workflow.GetSignalChannel(ctx, "complete")
19+
20+
for !isComplete {
21+
workflow.ExecuteActivity(ctx, SendEmailActivity, "Sleeping for 30 days")
22+
selector := workflow.NewSelector(ctx)
23+
selector.AddFuture(workflow.NewTimer(ctx, time.Hour*24*30), func(f workflow.Future) {})
24+
selector.AddReceive(sigChan, func(c workflow.ReceiveChannel, more bool) {
25+
isComplete = true
26+
})
27+
selector.Select(ctx)
28+
}
29+
30+
return "done", nil
31+
}
32+
33+
// A stub Activity for sending an email.
34+
func SendEmailActivity(ctx context.Context, msg string) error {
35+
activity.GetLogger(ctx).Info(fmt.Sprintf(`Sending email: "%v"\n`, msg))
36+
return nil
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package sleepfordays
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/stretchr/testify/mock"
8+
"github.com/stretchr/testify/require"
9+
10+
"go.temporal.io/sdk/testsuite"
11+
)
12+
13+
func TestSleepForDaysWorkflow(t *testing.T) {
14+
testSuite := &testsuite.WorkflowTestSuite{}
15+
env := testSuite.NewTestWorkflowEnvironment()
16+
17+
numActivityCalls := 0
18+
env.RegisterActivity(SendEmailActivity)
19+
env.OnActivity(SendEmailActivity, mock.Anything, mock.Anything).Run(
20+
func(args mock.Arguments) { numActivityCalls++ },
21+
).Return(nil)
22+
23+
startTime := env.Now()
24+
25+
// Time-skip 90 days.
26+
env.RegisterDelayedCallback(func() {
27+
// Check that the activity has been called 3 times.
28+
require.Equal(t, 3, numActivityCalls)
29+
// Send the signal to complete the workflow.
30+
env.SignalWorkflow("complete", nil)
31+
// Expect no more activity calls to have been made - workflow is complete.
32+
require.Equal(t, 3, numActivityCalls)
33+
// Expect more than 90 days to have passed.
34+
require.Equal(t, env.Now().Sub(startTime), time.Hour*24*90)
35+
}, time.Hour*24*90)
36+
37+
// Execute workflow.
38+
env.ExecuteWorkflow(SleepForDaysWorkflow)
39+
}

‎sleep-for-days/starter/main.go

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"log"
6+
7+
sleepfordays "github.com/temporalio/samples-go/sleep-for-days"
8+
"go.temporal.io/sdk/client"
9+
)
10+
11+
func main() {
12+
c, err := client.Dial(client.Options{})
13+
if err != nil {
14+
log.Fatalln("Unable to create client", err)
15+
}
16+
defer c.Close()
17+
18+
workflowOptions := client.StartWorkflowOptions{
19+
TaskQueue: "sleep-for-days",
20+
}
21+
22+
we, err := c.ExecuteWorkflow(context.Background(), workflowOptions, sleepfordays.SleepForDaysWorkflow)
23+
if err != nil {
24+
log.Fatalln("Unable to execute workflow", err)
25+
}
26+
27+
log.Println("Started sleep-for-days workflow", "WorkflowID", we.GetID(), "RunID", we.GetRunID())
28+
29+
// Synchronously wait for the workflow completion (will run indefinitely until it receives a signal)
30+
var result string
31+
err = we.Get(context.Background(), &result)
32+
if err != nil {
33+
log.Fatalln("Unable get workflow result", err)
34+
}
35+
log.Println("Workflow result:", result)
36+
}

‎sleep-for-days/worker/main.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package main
2+
3+
import (
4+
"log"
5+
6+
"go.temporal.io/sdk/client"
7+
"go.temporal.io/sdk/worker"
8+
9+
sleepfordays "github.com/temporalio/samples-go/sleep-for-days"
10+
)
11+
12+
func main() {
13+
// The client and worker are heavyweight objects that should be created once per process.
14+
c, err := client.Dial(client.Options{})
15+
if err != nil {
16+
log.Fatalln("Unable to create client", err)
17+
}
18+
defer c.Close()
19+
20+
w := worker.New(c, "sleep-for-days", worker.Options{})
21+
22+
w.RegisterWorkflow(sleepfordays.SleepForDaysWorkflow)
23+
w.RegisterActivity(sleepfordays.SendEmailActivity)
24+
25+
err = w.Run(worker.InterruptCh())
26+
if err != nil {
27+
log.Fatalln("Unable to start worker", err)
28+
}
29+
}

0 commit comments

Comments
 (0)
Please sign in to comment.