Skip to content

Commit

Permalink
Add sleep-for-days sample (#384)
Browse files Browse the repository at this point in the history
* sleep-for-days sample

* add test, fixed bugs
  • Loading branch information
THardy98 authored Feb 6, 2025
1 parent e0cc741 commit 4f4d6ef
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 0 deletions.
16 changes: 16 additions & 0 deletions sleep-for-days/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
### Sleep for days

This sample demonstrates how to create a Temporal workflow that runs forever, sending an email every 30 days.

### Steps to run this sample:
1) Run a [Temporal service](https://github.com/temporalio/samples-go/tree/main/#how-to-use).
2) Run the following command to start the worker
```
go run worker/main.go
```
3) Run the following command to start the example
```
go run starter/main.go
```

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 changes: 37 additions & 0 deletions sleep-for-days/sleepfordays_workflow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package sleepfordays

import (
"context"
"fmt"
"time"

"go.temporal.io/sdk/activity"
"go.temporal.io/sdk/workflow"
)

func SleepForDaysWorkflow(ctx workflow.Context) (string, error) {
ctx = workflow.WithActivityOptions(ctx, workflow.ActivityOptions{
StartToCloseTimeout: 10 * time.Second,
})

isComplete := false
sigChan := workflow.GetSignalChannel(ctx, "complete")

for !isComplete {
workflow.ExecuteActivity(ctx, SendEmailActivity, "Sleeping for 30 days")
selector := workflow.NewSelector(ctx)
selector.AddFuture(workflow.NewTimer(ctx, time.Hour*24*30), func(f workflow.Future) {})
selector.AddReceive(sigChan, func(c workflow.ReceiveChannel, more bool) {
isComplete = true
})
selector.Select(ctx)
}

return "done", nil
}

// A stub Activity for sending an email.
func SendEmailActivity(ctx context.Context, msg string) error {
activity.GetLogger(ctx).Info(fmt.Sprintf(`Sending email: "%v"\n`, msg))
return nil
}
39 changes: 39 additions & 0 deletions sleep-for-days/sleepfordays_workflow_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package sleepfordays

import (
"testing"
"time"

"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"

"go.temporal.io/sdk/testsuite"
)

func TestSleepForDaysWorkflow(t *testing.T) {
testSuite := &testsuite.WorkflowTestSuite{}
env := testSuite.NewTestWorkflowEnvironment()

numActivityCalls := 0
env.RegisterActivity(SendEmailActivity)
env.OnActivity(SendEmailActivity, mock.Anything, mock.Anything).Run(
func(args mock.Arguments) { numActivityCalls++ },
).Return(nil)

startTime := env.Now()

// Time-skip 90 days.
env.RegisterDelayedCallback(func() {
// Check that the activity has been called 3 times.
require.Equal(t, 3, numActivityCalls)
// Send the signal to complete the workflow.
env.SignalWorkflow("complete", nil)
// Expect no more activity calls to have been made - workflow is complete.
require.Equal(t, 3, numActivityCalls)
// Expect more than 90 days to have passed.
require.Equal(t, env.Now().Sub(startTime), time.Hour*24*90)
}, time.Hour*24*90)

// Execute workflow.
env.ExecuteWorkflow(SleepForDaysWorkflow)
}
36 changes: 36 additions & 0 deletions sleep-for-days/starter/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

import (
"context"
"log"

sleepfordays "github.com/temporalio/samples-go/sleep-for-days"
"go.temporal.io/sdk/client"
)

func main() {
c, err := client.Dial(client.Options{})
if err != nil {
log.Fatalln("Unable to create client", err)
}
defer c.Close()

workflowOptions := client.StartWorkflowOptions{
TaskQueue: "sleep-for-days",
}

we, err := c.ExecuteWorkflow(context.Background(), workflowOptions, sleepfordays.SleepForDaysWorkflow)
if err != nil {
log.Fatalln("Unable to execute workflow", err)
}

log.Println("Started sleep-for-days workflow", "WorkflowID", we.GetID(), "RunID", we.GetRunID())

// Synchronously wait for the workflow completion (will run indefinitely until it receives a signal)
var result string
err = we.Get(context.Background(), &result)
if err != nil {
log.Fatalln("Unable get workflow result", err)
}
log.Println("Workflow result:", result)
}
29 changes: 29 additions & 0 deletions sleep-for-days/worker/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package main

import (
"log"

"go.temporal.io/sdk/client"
"go.temporal.io/sdk/worker"

sleepfordays "github.com/temporalio/samples-go/sleep-for-days"
)

func main() {
// The client and worker are heavyweight objects that should be created once per process.
c, err := client.Dial(client.Options{})
if err != nil {
log.Fatalln("Unable to create client", err)
}
defer c.Close()

w := worker.New(c, "sleep-for-days", worker.Options{})

w.RegisterWorkflow(sleepfordays.SleepForDaysWorkflow)
w.RegisterActivity(sleepfordays.SendEmailActivity)

err = w.Run(worker.InterruptCh())
if err != nil {
log.Fatalln("Unable to start worker", err)
}
}

0 comments on commit 4f4d6ef

Please sign in to comment.