Schedule
A simple example showcasing usage of proto workflwos with Temporal schedules.
example.proto
syntax = "proto3";
package example.schedule.v1;
import "google/protobuf/timestamp.proto";
import "temporal/v1/temporal.proto";
service Example {
option (temporal.v1.service).task_queue = "schedule-v1";
rpc Schedule(ScheduleInput) returns (ScheduleOutput) {
option (temporal.v1.workflow) = {
name: "example.schedule.v1.Schedule"
};
}
}
message ScheduleInput {}
message ScheduleOutput {
google.protobuf.Timestamp started_at = 1;
}
main.go
package main
import (
"fmt"
"log"
"os"
"time"
schedulev1 "github.com/cludden/protoc-gen-go-temporal/gen/example/schedule/v1"
"github.com/urfave/cli/v2"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/worker"
"go.temporal.io/sdk/workflow"
"google.golang.org/protobuf/types/known/timestamppb"
)
type (
Workflows struct{}
ScheduleWorkflow struct {
*schedulev1.ScheduleWorkflowInput
}
)
func main() {
app, err := schedulev1.NewExampleCli(
schedulev1.NewExampleCliOptions().
WithClient(withClient).
WithWorker(func(cmd *cli.Context, c client.Client) (worker.Worker, error) {
w := worker.New(c, schedulev1.ExampleTaskQueue, worker.Options{})
schedulev1.RegisterExampleWorkflows(w, &Workflows{})
return w, nil
}),
)
if err != nil {
log.Fatal(err)
}
app.Commands = append(app.Commands, &cli.Command{
Name: "create-schedule",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "id",
Usage: "schedule id",
Value: "schedule_id",
},
},
Action: func(cmd *cli.Context) error {
c, err := withClient(cmd)
if err != nil {
return err
}
defer c.Close()
h, err := c.ScheduleClient().Create(cmd.Context, client.ScheduleOptions{
ID: cmd.String("id"),
Spec: client.ScheduleSpec{
Intervals: []client.ScheduleIntervalSpec{{
Every: time.Minute,
}},
},
Action: &client.ScheduleWorkflowAction{
ID: fmt.Sprintf("%s/", schedulev1.ScheduleWorkflowName),
Workflow: schedulev1.ScheduleWorkflowName,
TaskQueue: schedulev1.ExampleTaskQueue,
Args: []any{
&schedulev1.ScheduleInput{},
},
},
})
if err != nil {
return err
}
fmt.Printf("schedule created: %s\n", h.GetID())
return nil
},
})
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
func (w *Workflows) Schedule(ctx workflow.Context, input *schedulev1.ScheduleWorkflowInput) (schedulev1.ScheduleWorkflow, error) {
return &ScheduleWorkflow{input}, nil
}
func (w *ScheduleWorkflow) Execute(ctx workflow.Context) (*schedulev1.ScheduleOutput, error) {
return &schedulev1.ScheduleOutput{
StartedAt: timestamppb.New(workflow.Now(ctx)),
}, nil
}
func withClient(cmd *cli.Context) (client.Client, error) {
c, err := client.DialContext(cmd.Context, client.Options{})
if err != nil {
return nil, err
}
return c, nil
}
Run this example
- Clone the examples
git clone https://github.com/cludden/protoc-gen-go-temporal && cd protoc-gen-go-temporal
- Start temporal
temporal server start-dev
- In a different terminal, run the worker
go run ./examples/schedule/... worker
- In a different terminal, create a schedule
go run ./examples/schedule/... create-schedule