feat: support one-time scheduled workflows (#84)

* feat: support one-time scheduled workflows

* refactor: move schedule out of workflow trigger def

* docs: add scheduling workflows section

* docs: update creating workflow

* only cancel schedules that are in the future
This commit is contained in:
abelanger5
2024-01-08 10:03:32 -05:00
committed by GitHub
parent 7d1cf5400f
commit 62445dc37f
29 changed files with 1378 additions and 410 deletions

View File

@@ -9,6 +9,7 @@ import "google/protobuf/wrappers.proto"; // For optional fields
service WorkflowService {
rpc ListWorkflows(ListWorkflowsRequest) returns (ListWorkflowsResponse);
rpc PutWorkflow(PutWorkflowRequest) returns (WorkflowVersion);
rpc ScheduleWorkflow(ScheduleWorkflowRequest) returns (WorkflowVersion);
rpc GetWorkflowByName(GetWorkflowByNameRequest) returns (Workflow);
rpc ListWorkflowsForEvent(ListWorkflowsForEventRequest) returns (ListWorkflowsResponse);
rpc DeleteWorkflow(DeleteWorkflowRequest) returns (Workflow);
@@ -26,7 +27,8 @@ message CreateWorkflowVersionOpts {
string version = 3; // (required) the workflow version
repeated string event_triggers = 4; // (optional) event triggers for the workflow
repeated string cron_triggers = 5; // (optional) cron triggers for the workflow
repeated CreateWorkflowJobOpts jobs = 6; // (required) the workflow jobs
repeated google.protobuf.Timestamp scheduled_triggers = 6; // (optional) scheduled triggers for the workflow
repeated CreateWorkflowJobOpts jobs = 7; // (required) the workflow jobs
}
// CreateWorkflowJobOpts represents options to create a workflow job.
@@ -49,7 +51,13 @@ message CreateWorkflowStepOpts {
message ListWorkflowsRequest {
string tenant_id = 1;
}
message ScheduleWorkflowRequest {
string tenant_id = 1;
string workflow_id = 2;
repeated google.protobuf.Timestamp schedules = 3;
}
// ListWorkflowsResponse is the response for ListWorkflows.
message ListWorkflowsResponse {
repeated Workflow workflows = 1;

View File

@@ -2,6 +2,7 @@ package main
import (
"fmt"
"log"
"os"
"sync"
@@ -15,6 +16,9 @@ import (
"github.com/hatchet-dev/hatchet/internal/services/ticker"
"github.com/hatchet-dev/hatchet/pkg/cmdutils"
"github.com/spf13/cobra"
"net/http"
_ "net/http/pprof"
)
var printVersion bool
@@ -33,6 +37,11 @@ var rootCmd = &cobra.Command{
cf := loader.NewConfigLoader(configDirectory)
interruptChan := cmdutils.InterruptChan()
// TODO: configurable via env var
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
startEngineOrDie(cf, interruptChan)
},
}

View File

@@ -11,6 +11,13 @@ import (
)
type printInput struct{}
type printOutput struct{}
func print(ctx context.Context, input *printInput) (result *printOutput, err error) {
fmt.Println("called print:print")
return &printOutput{}, nil
}
func main() {
err := godotenv.Load()
@@ -39,11 +46,9 @@ func main() {
panic(err)
}
err = worker.RegisterAction("print:print", func(ctx context.Context, input *printInput) (result any, err error) {
fmt.Println("called print:print")
printSvc := worker.NewService("print")
return map[string]interface{}{}, nil
})
err = printSvc.RegisterAction(print)
if err != nil {
panic(err)

112
examples/scheduled/main.go Normal file
View File

@@ -0,0 +1,112 @@
package main
import (
"context"
"fmt"
"time"
"github.com/hatchet-dev/hatchet/pkg/client"
"github.com/hatchet-dev/hatchet/pkg/cmdutils"
"github.com/hatchet-dev/hatchet/pkg/worker"
"github.com/joho/godotenv"
)
type userCreateEvent struct {
Username string `json:"username"`
UserId string `json:"user_id"`
Data map[string]string `json:"data"`
}
type stepOneOutput struct {
Message string `json:"message"`
}
func StepOne(ctx context.Context, input *userCreateEvent) (result *stepOneOutput, err error) {
fmt.Println("this ran at: ", time.Now())
return &stepOneOutput{
Message: "This ran at: " + time.Now().Format(time.RubyDate),
}, nil
}
func main() {
err := godotenv.Load()
if err != nil {
panic(err)
}
client, err := client.New()
if err != nil {
panic(err)
}
// Create a worker. This automatically reads in a TemporalClient from .env and workflow files from the .hatchet
// directory, but this can be customized with the `worker.WithTemporalClient` and `worker.WithWorkflowFiles` options.
w, err := worker.NewWorker(
worker.WithClient(
client,
),
)
if err != nil {
panic(err)
}
err = w.On(
worker.At(time.Now().Add(time.Second*10)),
&worker.WorkflowJob{
Name: "scheduled-workflow",
Description: "This runs at a scheduled time.",
Steps: []worker.WorkflowStep{
worker.Fn(StepOne).SetName("step-one"),
},
},
)
if err != nil {
panic(err)
}
interruptCtx, cancel := cmdutils.InterruptContextFromChan(cmdutils.InterruptChan())
defer cancel()
go func() {
err = w.Start(interruptCtx)
if err != nil {
panic(err)
}
cancel()
}()
go func() {
time.Sleep(5 * time.Second)
at := []time.Time{}
for i := 0; i < 99; i++ {
at = append(at, time.Now().Add(time.Second*30+time.Millisecond*10*time.Duration(i)))
}
err = client.Admin().ScheduleWorkflow(
"scheduled-workflow",
at...,
)
if err != nil {
panic(err)
}
}()
for {
select {
case <-interruptCtx.Done():
return
default:
time.Sleep(time.Second)
}
}
}

View File

@@ -0,0 +1,6 @@
{
"creating-a-worker": "Creating a Worker",
"creating-a-workflow": "Creating a Workflow",
"pushing-events": "Pushing Events",
"scheduling-workflows": "Scheduling Workflows"
}

View File

@@ -24,6 +24,7 @@ w.On(
- `worker.Events` - triggers a workflow when any of the given events are received
- `worker.Cron` - triggers a workflow on a cron schedule
- `worker.Crons` - triggers a workflow from multiple cron schedules
- `worker.At` - triggers a workflow at a specific time. This is useful for one-off workflows. You can also schedule workflows using the `Admin` API - see [here](./scheduling-workflows) for more information.
**Supported Workflow Definitions**

View File

@@ -0,0 +1,18 @@
# Scheduling Workflows
You can schedule workflows for specific times with the client's `Admin().ScheduleWorkflow` method:
```go
c, err := client.New(
client.WithHostPort("127.0.0.1", 7077),
)
if err != nil {
panic(err)
}
client.Admin().ScheduleWorkflow(
"scheduled-workflow", // the name of the workflow
time.Now().Add(10 * time.Second),
)
```

10
go.mod
View File

@@ -2,14 +2,12 @@ module github.com/hatchet-dev/hatchet
go 1.21
// this line is necessary because Temporal relies on an old version of exp
replace golang.org/x/exp => golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1
require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/creasty/defaults v1.7.0
github.com/fatih/color v1.16.0
github.com/getkin/kin-openapi v0.122.0
github.com/go-co-op/gocron/v2 v2.1.2
github.com/gorilla/securecookie v1.1.2
github.com/gorilla/sessions v1.2.2
github.com/hashicorp/go-multierror v1.1.1
@@ -40,6 +38,7 @@ require (
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/labstack/gommon v0.4.0 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
@@ -49,6 +48,7 @@ require (
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/exp v0.0.0-20231219180239-dc181d75b848 // indirect
golang.org/x/time v0.3.0 // indirect
)
@@ -57,11 +57,10 @@ require (
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/getsentry/sentry-go v0.25.0
github.com/go-chi/chi v1.5.5
github.com/go-co-op/gocron v1.36.0
github.com/go-playground/validator/v10 v10.16.0
github.com/go-test/deep v1.1.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/uuid v1.4.0
github.com/google/uuid v1.5.0
github.com/gorilla/schema v1.2.1
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
@@ -81,7 +80,6 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.8.4
github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
golang.org/x/crypto v0.17.0
golang.org/x/net v0.17.0 // indirect
golang.org/x/sync v0.4.0

68
go.sum
View File

@@ -35,7 +35,9 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
@@ -79,10 +81,13 @@ github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX
github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE=
github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw=
github.com/go-co-op/gocron v1.36.0 h1:sEmAwg57l4JWQgzaVWYfKZ+w13uHOqeOtwjo72Ll5Wc=
github.com/go-co-op/gocron v1.36.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY=
github.com/go-co-op/gocron/v2 v2.1.2 h1:+6tTOA9aBaKXpDWExw07hYoGEBzT+4CkGSVAiJ7WSXs=
github.com/go-co-op/gocron/v2 v2.1.2/go.mod h1:0MfNAXEchzeSH1vtkZrTAcSMWqyL435kL6CA4b0bjrg=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
@@ -143,7 +148,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
@@ -163,8 +167,8 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
@@ -205,6 +209,8 @@ github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
@@ -214,7 +220,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -251,7 +256,6 @@ github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
@@ -264,8 +268,6 @@ github.com/rabbitmq/amqp091-go v1.9.0/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
@@ -318,30 +320,38 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20231219180239-dc181d75b848 h1:+iq7lrkxmFNBM7xx+Rae2W6uyPfhPeDWD+n+JgppptE=
golang.org/x/exp v0.0.0-20231219180239-dc181d75b848/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -353,15 +363,16 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -394,8 +405,6 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -417,17 +426,18 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -456,18 +466,13 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -476,7 +481,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -488,6 +492,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
@@ -495,7 +500,9 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -507,6 +514,7 @@ golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
@@ -527,8 +535,6 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -109,3 +109,23 @@ func (t *tickerRepository) RemoveCron(tickerId string, cron *db.WorkflowTriggerC
),
).Exec(context.Background())
}
func (t *tickerRepository) AddScheduledWorkflow(tickerId string, schedule *db.WorkflowTriggerScheduledRefModel) (*db.TickerModel, error) {
return t.client.Ticker.FindUnique(
db.Ticker.ID.Equals(tickerId),
).Update(
db.Ticker.Scheduled.Link(
db.WorkflowTriggerScheduledRef.ID.Equals(schedule.ID),
),
).Exec(context.Background())
}
func (t *tickerRepository) RemoveScheduledWorkflow(tickerId string, schedule *db.WorkflowTriggerScheduledRefModel) (*db.TickerModel, error) {
return t.client.Ticker.FindUnique(
db.Ticker.ID.Equals(tickerId),
).Update(
db.Ticker.Scheduled.Unlink(
db.WorkflowTriggerScheduledRef.ID.Equals(schedule.ID),
),
).Exec(context.Background())
}

View File

@@ -279,6 +279,48 @@ func (r *workflowRepository) CreateWorkflowVersion(tenantId string, opts *reposi
).Exec(context.Background())
}
type createScheduleTxResult interface {
Result() *db.WorkflowTriggerScheduledRefModel
}
func (r *workflowRepository) CreateSchedules(
tenantId, workflowVersionId string,
opts *repository.CreateWorkflowSchedulesOpts,
) ([]*db.WorkflowTriggerScheduledRefModel, error) {
if err := r.v.Validate(opts); err != nil {
return nil, err
}
txs := []transaction.Param{}
results := []createScheduleTxResult{}
for _, scheduledTrigger := range opts.ScheduledTriggers {
createTx := r.client.WorkflowTriggerScheduledRef.CreateOne(
db.WorkflowTriggerScheduledRef.Parent.Link(
db.WorkflowVersion.ID.Equals(workflowVersionId),
),
db.WorkflowTriggerScheduledRef.TriggerAt.Set(scheduledTrigger),
).Tx()
txs = append(txs, createTx)
results = append(results, createTx)
}
err := r.client.Prisma.Transaction(txs...).Exec(context.Background())
if err != nil {
return nil, err
}
res := make([]*db.WorkflowTriggerScheduledRefModel, 0)
for _, result := range results {
res = append(res, result.Result())
}
return res, nil
}
func (r *workflowRepository) GetWorkflowById(workflowId string) (*db.WorkflowModel, error) {
return r.client.Workflow.FindUnique(
db.Workflow.ID.Equals(workflowId),
@@ -455,6 +497,15 @@ func (r *workflowRepository) createWorkflowVersionTxs(tenantId, workflowId strin
).Tx())
}
for _, scheduledTrigger := range opts.ScheduledTriggers {
txs = append(txs, r.client.WorkflowTriggerScheduledRef.CreateOne(
db.WorkflowTriggerScheduledRef.Parent.Link(
db.WorkflowVersion.ID.Equals(workflowVersionId),
),
db.WorkflowTriggerScheduledRef.TriggerAt.Set(scheduledTrigger),
).Tx())
}
return workflowVersionId, txs
}
@@ -499,5 +550,8 @@ func defaultWorkflowVersionPopulator() []db.WorkflowVersionRelationWith {
db.Step.Action.Fetch(),
),
),
db.WorkflowVersion.Scheduled.Fetch().With(
db.WorkflowTriggerScheduledRef.Ticker.Fetch(),
),
}
}

View File

@@ -153,6 +153,12 @@ func (w *workflowRunRepository) CreateNewWorkflowRun(tenantId string, opts *repo
))
}
if opts.ScheduledWorkflowId != nil {
triggerOptionals = append(triggerOptionals, db.WorkflowRunTriggeredBy.Scheduled.Link(
db.WorkflowTriggerScheduledRef.ID.Equals(*opts.ScheduledWorkflowId),
))
}
// create the trigger definition
txs = append(txs, w.client.WorkflowRunTriggeredBy.CreateOne(
db.WorkflowRunTriggeredBy.Tenant.Link(

View File

@@ -43,4 +43,10 @@ type TickerRepository interface {
// RemoveCron removes a cron from a ticker.
RemoveCron(tickerId string, cron *db.WorkflowTriggerCronRefModel) (*db.TickerModel, error)
// AddScheduledWorkflow assigns a scheduled workflow to a ticker.
AddScheduledWorkflow(tickerId string, schedule *db.WorkflowTriggerScheduledRefModel) (*db.TickerModel, error)
// RemoveScheduledWorkflow removes a scheduled workflow from a ticker.
RemoveScheduledWorkflow(tickerId string, schedule *db.WorkflowTriggerScheduledRefModel) (*db.TickerModel, error)
}

View File

@@ -1,6 +1,8 @@
package repository
import (
"time"
"github.com/hatchet-dev/hatchet/internal/repository/prisma/db"
)
@@ -22,10 +24,17 @@ type CreateWorkflowVersionOpts struct {
// (optional) cron triggers for the workflow
CronTriggers []string `validate:"dive,cron"`
// (optional) scheduled triggers for the workflow
ScheduledTriggers []time.Time
// (required) the workflow jobs
Jobs []CreateWorkflowJobOpts `validate:"required,min=1,dive"`
}
type CreateWorkflowSchedulesOpts struct {
ScheduledTriggers []time.Time
}
type CreateWorkflowTagOpts struct {
// (required) the tag name
Name string `validate:"required"`
@@ -96,6 +105,9 @@ type WorkflowRepository interface {
// not a parent workflow with the same name already in the database.
CreateWorkflowVersion(tenantId string, opts *CreateWorkflowVersionOpts) (*db.WorkflowVersionModel, error)
// CreateSchedules creates schedules for a given workflow version.
CreateSchedules(tenantId, workflowVersionId string, opts *CreateWorkflowSchedulesOpts) ([]*db.WorkflowTriggerScheduledRefModel, error)
// GetWorkflowById returns a workflow by its name. It will return db.ErrNotFound if the workflow does not exist.
GetWorkflowById(workflowId string) (*db.WorkflowModel, error)

View File

@@ -9,6 +9,7 @@ import (
"github.com/hatchet-dev/hatchet/internal/iter"
"github.com/hatchet-dev/hatchet/internal/repository/prisma/db"
"github.com/hatchet-dev/hatchet/internal/repository/prisma/dbsqlc"
"github.com/steebchen/prisma-client-go/runtime/types"
)
type CreateWorkflowRunOpts struct {
@@ -16,11 +17,14 @@ type CreateWorkflowRunOpts struct {
WorkflowVersionId string `validate:"required,uuid"`
// (optional) the event id that triggered the workflow run
TriggeringEventId *string `validate:"omitnil,uuid,required_without=Cron,excluded_with=Cron"`
TriggeringEventId *string `validate:"omitnil,uuid,required_without=Cron,required_without=ScheduledWorkflowId,excluded_with=Cron,excluded_with=ScheduledWorkflowId"`
// (optional) the cron schedule that triggered the workflow run
Cron *string `validate:"omitnil,cron,required_without=TriggeringEventId,excluded_with=TriggeringEventId"`
CronParentId *string `validate:"omitempty,uuid,required_without=TriggeringEventId,excluded_with=TriggeringEventId"`
Cron *string `validate:"omitnil,cron,required_without=TriggeringEventId,required_without=ScheduledWorkflowId,excluded_with=TriggeringEventId,excluded_with=ScheduledWorkflowId"`
CronParentId *string `validate:"omitnil,uuid,required_without=TriggeringEventId,required_without=ScheduledWorkflowId,excluded_with=TriggeringEventId,excluded_with=ScheduledWorkflowId"`
// (optional) the scheduled trigger
ScheduledWorkflowId *string `validate:"omitnil,uuid,required_without=TriggeringEventId,required_without=Cron,excluded_with=TriggeringEventId,excluded_with=Cron"`
// (required) the workflow jobs
JobRuns []CreateWorkflowJobRunOpts `validate:"required,min=1,dive"`
@@ -47,36 +51,9 @@ func GetCreateWorkflowRunOptsFromEvent(event *db.EventModel, workflowVersion *db
TriggeringEventId: &eventId,
}
for _, job := range workflowVersion.Jobs() {
jobOpts := CreateWorkflowJobRunOpts{
JobId: job.ID,
Input: jobRunData,
}
opts.JobRuns, err = getJobsFromWorkflowVersion(workflowVersion, jobRunData)
iter, err := iter.New(job.Steps())
if err != nil {
return nil, fmt.Errorf("could not create step iterator: %w", err)
}
for {
step, ok := iter.Next()
if !ok {
break
}
stepOpts := CreateWorkflowStepRunOpts{
StepId: step.ID,
}
jobOpts.StepRuns = append(jobOpts.StepRuns, stepOpts)
}
opts.JobRuns = append(opts.JobRuns, jobOpts)
}
return opts, nil
return opts, err
}
func GetCreateWorkflowRunOptsFromCron(cron, cronParentId string, workflowVersion *db.WorkflowVersionModel) (*CreateWorkflowRunOpts, error) {
@@ -92,6 +69,31 @@ func GetCreateWorkflowRunOptsFromCron(cron, cronParentId string, workflowVersion
CronParentId: &cronParentId,
}
opts.JobRuns, err = getJobsFromWorkflowVersion(workflowVersion, jobRunData)
return opts, err
}
func GetCreateWorkflowRunOptsFromSchedule(scheduledWorkflowId string, workflowVersion *db.WorkflowVersionModel) (*CreateWorkflowRunOpts, error) {
jobRunData, err := datautils.ToJSONType(map[string]interface{}{})
if err != nil {
return nil, fmt.Errorf("could not convert job run lookup data to json: %w", err)
}
opts := &CreateWorkflowRunOpts{
WorkflowVersionId: workflowVersion.ID,
ScheduledWorkflowId: &scheduledWorkflowId,
}
opts.JobRuns, err = getJobsFromWorkflowVersion(workflowVersion, jobRunData)
return opts, err
}
func getJobsFromWorkflowVersion(workflowVersion *db.WorkflowVersionModel, jobRunData *types.JSON) ([]CreateWorkflowJobRunOpts, error) {
resJobRunOpts := []CreateWorkflowJobRunOpts{}
for _, job := range workflowVersion.Jobs() {
jobOpts := CreateWorkflowJobRunOpts{
JobId: job.ID,
@@ -118,10 +120,10 @@ func GetCreateWorkflowRunOptsFromCron(cron, cronParentId string, workflowVersion
jobOpts.StepRuns = append(jobOpts.StepRuns, stepOpts)
}
opts.JobRuns = append(opts.JobRuns, jobOpts)
resJobRunOpts = append(resJobRunOpts, jobOpts)
}
return opts, nil
return resJobRunOpts, nil
}
type CreateWorkflowJobRunOpts struct {

View File

@@ -83,12 +83,13 @@ type CreateWorkflowVersionOpts struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // (required) the workflow name
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` // (optional) the workflow description
Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` // (required) the workflow version
EventTriggers []string `protobuf:"bytes,4,rep,name=event_triggers,json=eventTriggers,proto3" json:"event_triggers,omitempty"` // (optional) event triggers for the workflow
CronTriggers []string `protobuf:"bytes,5,rep,name=cron_triggers,json=cronTriggers,proto3" json:"cron_triggers,omitempty"` // (optional) cron triggers for the workflow
Jobs []*CreateWorkflowJobOpts `protobuf:"bytes,6,rep,name=jobs,proto3" json:"jobs,omitempty"` // (required) the workflow jobs
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // (required) the workflow name
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` // (optional) the workflow description
Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` // (required) the workflow version
EventTriggers []string `protobuf:"bytes,4,rep,name=event_triggers,json=eventTriggers,proto3" json:"event_triggers,omitempty"` // (optional) event triggers for the workflow
CronTriggers []string `protobuf:"bytes,5,rep,name=cron_triggers,json=cronTriggers,proto3" json:"cron_triggers,omitempty"` // (optional) cron triggers for the workflow
ScheduledTriggers []*timestamppb.Timestamp `protobuf:"bytes,6,rep,name=scheduled_triggers,json=scheduledTriggers,proto3" json:"scheduled_triggers,omitempty"` // (optional) scheduled triggers for the workflow
Jobs []*CreateWorkflowJobOpts `protobuf:"bytes,7,rep,name=jobs,proto3" json:"jobs,omitempty"` // (required) the workflow jobs
}
func (x *CreateWorkflowVersionOpts) Reset() {
@@ -158,6 +159,13 @@ func (x *CreateWorkflowVersionOpts) GetCronTriggers() []string {
return nil
}
func (x *CreateWorkflowVersionOpts) GetScheduledTriggers() []*timestamppb.Timestamp {
if x != nil {
return x.ScheduledTriggers
}
return nil
}
func (x *CreateWorkflowVersionOpts) GetJobs() []*CreateWorkflowJobOpts {
if x != nil {
return x.Jobs
@@ -357,6 +365,69 @@ func (x *ListWorkflowsRequest) GetTenantId() string {
return ""
}
type ScheduleWorkflowRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
TenantId string `protobuf:"bytes,1,opt,name=tenant_id,json=tenantId,proto3" json:"tenant_id,omitempty"`
WorkflowId string `protobuf:"bytes,2,opt,name=workflow_id,json=workflowId,proto3" json:"workflow_id,omitempty"`
Schedules []*timestamppb.Timestamp `protobuf:"bytes,3,rep,name=schedules,proto3" json:"schedules,omitempty"`
}
func (x *ScheduleWorkflowRequest) Reset() {
*x = ScheduleWorkflowRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_workflows_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ScheduleWorkflowRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ScheduleWorkflowRequest) ProtoMessage() {}
func (x *ScheduleWorkflowRequest) ProtoReflect() protoreflect.Message {
mi := &file_workflows_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ScheduleWorkflowRequest.ProtoReflect.Descriptor instead.
func (*ScheduleWorkflowRequest) Descriptor() ([]byte, []int) {
return file_workflows_proto_rawDescGZIP(), []int{5}
}
func (x *ScheduleWorkflowRequest) GetTenantId() string {
if x != nil {
return x.TenantId
}
return ""
}
func (x *ScheduleWorkflowRequest) GetWorkflowId() string {
if x != nil {
return x.WorkflowId
}
return ""
}
func (x *ScheduleWorkflowRequest) GetSchedules() []*timestamppb.Timestamp {
if x != nil {
return x.Schedules
}
return nil
}
// ListWorkflowsResponse is the response for ListWorkflows.
type ListWorkflowsResponse struct {
state protoimpl.MessageState
@@ -369,7 +440,7 @@ type ListWorkflowsResponse struct {
func (x *ListWorkflowsResponse) Reset() {
*x = ListWorkflowsResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_workflows_proto_msgTypes[5]
mi := &file_workflows_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -382,7 +453,7 @@ func (x *ListWorkflowsResponse) String() string {
func (*ListWorkflowsResponse) ProtoMessage() {}
func (x *ListWorkflowsResponse) ProtoReflect() protoreflect.Message {
mi := &file_workflows_proto_msgTypes[5]
mi := &file_workflows_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -395,7 +466,7 @@ func (x *ListWorkflowsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListWorkflowsResponse.ProtoReflect.Descriptor instead.
func (*ListWorkflowsResponse) Descriptor() ([]byte, []int) {
return file_workflows_proto_rawDescGZIP(), []int{5}
return file_workflows_proto_rawDescGZIP(), []int{6}
}
func (x *ListWorkflowsResponse) GetWorkflows() []*Workflow {
@@ -418,7 +489,7 @@ type ListWorkflowsForEventRequest struct {
func (x *ListWorkflowsForEventRequest) Reset() {
*x = ListWorkflowsForEventRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_workflows_proto_msgTypes[6]
mi := &file_workflows_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -431,7 +502,7 @@ func (x *ListWorkflowsForEventRequest) String() string {
func (*ListWorkflowsForEventRequest) ProtoMessage() {}
func (x *ListWorkflowsForEventRequest) ProtoReflect() protoreflect.Message {
mi := &file_workflows_proto_msgTypes[6]
mi := &file_workflows_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -444,7 +515,7 @@ func (x *ListWorkflowsForEventRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListWorkflowsForEventRequest.ProtoReflect.Descriptor instead.
func (*ListWorkflowsForEventRequest) Descriptor() ([]byte, []int) {
return file_workflows_proto_rawDescGZIP(), []int{6}
return file_workflows_proto_rawDescGZIP(), []int{7}
}
func (x *ListWorkflowsForEventRequest) GetTenantId() string {
@@ -479,7 +550,7 @@ type Workflow struct {
func (x *Workflow) Reset() {
*x = Workflow{}
if protoimpl.UnsafeEnabled {
mi := &file_workflows_proto_msgTypes[7]
mi := &file_workflows_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -492,7 +563,7 @@ func (x *Workflow) String() string {
func (*Workflow) ProtoMessage() {}
func (x *Workflow) ProtoReflect() protoreflect.Message {
mi := &file_workflows_proto_msgTypes[7]
mi := &file_workflows_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -505,7 +576,7 @@ func (x *Workflow) ProtoReflect() protoreflect.Message {
// Deprecated: Use Workflow.ProtoReflect.Descriptor instead.
func (*Workflow) Descriptor() ([]byte, []int) {
return file_workflows_proto_rawDescGZIP(), []int{7}
return file_workflows_proto_rawDescGZIP(), []int{8}
}
func (x *Workflow) GetId() string {
@@ -576,7 +647,7 @@ type WorkflowVersion struct {
func (x *WorkflowVersion) Reset() {
*x = WorkflowVersion{}
if protoimpl.UnsafeEnabled {
mi := &file_workflows_proto_msgTypes[8]
mi := &file_workflows_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -589,7 +660,7 @@ func (x *WorkflowVersion) String() string {
func (*WorkflowVersion) ProtoMessage() {}
func (x *WorkflowVersion) ProtoReflect() protoreflect.Message {
mi := &file_workflows_proto_msgTypes[8]
mi := &file_workflows_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -602,7 +673,7 @@ func (x *WorkflowVersion) ProtoReflect() protoreflect.Message {
// Deprecated: Use WorkflowVersion.ProtoReflect.Descriptor instead.
func (*WorkflowVersion) Descriptor() ([]byte, []int) {
return file_workflows_proto_rawDescGZIP(), []int{8}
return file_workflows_proto_rawDescGZIP(), []int{9}
}
func (x *WorkflowVersion) GetId() string {
@@ -679,7 +750,7 @@ type WorkflowTriggers struct {
func (x *WorkflowTriggers) Reset() {
*x = WorkflowTriggers{}
if protoimpl.UnsafeEnabled {
mi := &file_workflows_proto_msgTypes[9]
mi := &file_workflows_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -692,7 +763,7 @@ func (x *WorkflowTriggers) String() string {
func (*WorkflowTriggers) ProtoMessage() {}
func (x *WorkflowTriggers) ProtoReflect() protoreflect.Message {
mi := &file_workflows_proto_msgTypes[9]
mi := &file_workflows_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -705,7 +776,7 @@ func (x *WorkflowTriggers) ProtoReflect() protoreflect.Message {
// Deprecated: Use WorkflowTriggers.ProtoReflect.Descriptor instead.
func (*WorkflowTriggers) Descriptor() ([]byte, []int) {
return file_workflows_proto_rawDescGZIP(), []int{9}
return file_workflows_proto_rawDescGZIP(), []int{10}
}
func (x *WorkflowTriggers) GetId() string {
@@ -770,7 +841,7 @@ type WorkflowTriggerEventRef struct {
func (x *WorkflowTriggerEventRef) Reset() {
*x = WorkflowTriggerEventRef{}
if protoimpl.UnsafeEnabled {
mi := &file_workflows_proto_msgTypes[10]
mi := &file_workflows_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -783,7 +854,7 @@ func (x *WorkflowTriggerEventRef) String() string {
func (*WorkflowTriggerEventRef) ProtoMessage() {}
func (x *WorkflowTriggerEventRef) ProtoReflect() protoreflect.Message {
mi := &file_workflows_proto_msgTypes[10]
mi := &file_workflows_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -796,7 +867,7 @@ func (x *WorkflowTriggerEventRef) ProtoReflect() protoreflect.Message {
// Deprecated: Use WorkflowTriggerEventRef.ProtoReflect.Descriptor instead.
func (*WorkflowTriggerEventRef) Descriptor() ([]byte, []int) {
return file_workflows_proto_rawDescGZIP(), []int{10}
return file_workflows_proto_rawDescGZIP(), []int{11}
}
func (x *WorkflowTriggerEventRef) GetParentId() string {
@@ -826,7 +897,7 @@ type WorkflowTriggerCronRef struct {
func (x *WorkflowTriggerCronRef) Reset() {
*x = WorkflowTriggerCronRef{}
if protoimpl.UnsafeEnabled {
mi := &file_workflows_proto_msgTypes[11]
mi := &file_workflows_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -839,7 +910,7 @@ func (x *WorkflowTriggerCronRef) String() string {
func (*WorkflowTriggerCronRef) ProtoMessage() {}
func (x *WorkflowTriggerCronRef) ProtoReflect() protoreflect.Message {
mi := &file_workflows_proto_msgTypes[11]
mi := &file_workflows_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -852,7 +923,7 @@ func (x *WorkflowTriggerCronRef) ProtoReflect() protoreflect.Message {
// Deprecated: Use WorkflowTriggerCronRef.ProtoReflect.Descriptor instead.
func (*WorkflowTriggerCronRef) Descriptor() ([]byte, []int) {
return file_workflows_proto_rawDescGZIP(), []int{11}
return file_workflows_proto_rawDescGZIP(), []int{12}
}
func (x *WorkflowTriggerCronRef) GetParentId() string {
@@ -889,7 +960,7 @@ type Job struct {
func (x *Job) Reset() {
*x = Job{}
if protoimpl.UnsafeEnabled {
mi := &file_workflows_proto_msgTypes[12]
mi := &file_workflows_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -902,7 +973,7 @@ func (x *Job) String() string {
func (*Job) ProtoMessage() {}
func (x *Job) ProtoReflect() protoreflect.Message {
mi := &file_workflows_proto_msgTypes[12]
mi := &file_workflows_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -915,7 +986,7 @@ func (x *Job) ProtoReflect() protoreflect.Message {
// Deprecated: Use Job.ProtoReflect.Descriptor instead.
func (*Job) Descriptor() ([]byte, []int) {
return file_workflows_proto_rawDescGZIP(), []int{12}
return file_workflows_proto_rawDescGZIP(), []int{13}
}
func (x *Job) GetId() string {
@@ -1001,7 +1072,7 @@ type Step struct {
func (x *Step) Reset() {
*x = Step{}
if protoimpl.UnsafeEnabled {
mi := &file_workflows_proto_msgTypes[13]
mi := &file_workflows_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1014,7 +1085,7 @@ func (x *Step) String() string {
func (*Step) ProtoMessage() {}
func (x *Step) ProtoReflect() protoreflect.Message {
mi := &file_workflows_proto_msgTypes[13]
mi := &file_workflows_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1027,7 +1098,7 @@ func (x *Step) ProtoReflect() protoreflect.Message {
// Deprecated: Use Step.ProtoReflect.Descriptor instead.
func (*Step) Descriptor() ([]byte, []int) {
return file_workflows_proto_rawDescGZIP(), []int{13}
return file_workflows_proto_rawDescGZIP(), []int{14}
}
func (x *Step) GetId() string {
@@ -1105,7 +1176,7 @@ type DeleteWorkflowRequest struct {
func (x *DeleteWorkflowRequest) Reset() {
*x = DeleteWorkflowRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_workflows_proto_msgTypes[14]
mi := &file_workflows_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1118,7 +1189,7 @@ func (x *DeleteWorkflowRequest) String() string {
func (*DeleteWorkflowRequest) ProtoMessage() {}
func (x *DeleteWorkflowRequest) ProtoReflect() protoreflect.Message {
mi := &file_workflows_proto_msgTypes[14]
mi := &file_workflows_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1131,7 +1202,7 @@ func (x *DeleteWorkflowRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteWorkflowRequest.ProtoReflect.Descriptor instead.
func (*DeleteWorkflowRequest) Descriptor() ([]byte, []int) {
return file_workflows_proto_rawDescGZIP(), []int{14}
return file_workflows_proto_rawDescGZIP(), []int{15}
}
func (x *DeleteWorkflowRequest) GetTenantId() string {
@@ -1160,7 +1231,7 @@ type GetWorkflowByNameRequest struct {
func (x *GetWorkflowByNameRequest) Reset() {
*x = GetWorkflowByNameRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_workflows_proto_msgTypes[15]
mi := &file_workflows_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1173,7 +1244,7 @@ func (x *GetWorkflowByNameRequest) String() string {
func (*GetWorkflowByNameRequest) ProtoMessage() {}
func (x *GetWorkflowByNameRequest) ProtoReflect() protoreflect.Message {
mi := &file_workflows_proto_msgTypes[15]
mi := &file_workflows_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1186,7 +1257,7 @@ func (x *GetWorkflowByNameRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetWorkflowByNameRequest.ProtoReflect.Descriptor instead.
func (*GetWorkflowByNameRequest) Descriptor() ([]byte, []int) {
return file_workflows_proto_rawDescGZIP(), []int{15}
return file_workflows_proto_rawDescGZIP(), []int{16}
}
func (x *GetWorkflowByNameRequest) GetTenantId() string {
@@ -1217,7 +1288,7 @@ var file_workflows_proto_rawDesc = []byte{
0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b,
0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x73, 0x52,
0x04, 0x6f, 0x70, 0x74, 0x73, 0x22, 0xe3, 0x01, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
0x04, 0x6f, 0x70, 0x74, 0x73, 0x22, 0xae, 0x02, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4f,
0x70, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
@@ -1229,134 +1300,55 @@ var file_workflows_proto_rawDesc = []byte{
0x6e, 0x74, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x72,
0x6f, 0x6e, 0x5f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28,
0x09, 0x52, 0x0c, 0x63, 0x72, 0x6f, 0x6e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x12,
0x2a, 0x0a, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e,
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4a, 0x6f,
0x62, 0x4f, 0x70, 0x74, 0x73, 0x52, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x15,
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4a, 0x6f,
0x62, 0x4f, 0x70, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x74,
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69,
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x18, 0x04,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72,
0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x65, 0x70, 0x4f, 0x70, 0x74, 0x73, 0x52, 0x05, 0x73,
0x74, 0x65, 0x70, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57,
0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x65, 0x70, 0x4f, 0x70, 0x74, 0x73, 0x12,
0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x49, 0x64,
0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65,
0x6f, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f,
0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01,
0x28, 0x09, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x22, 0x33, 0x0a, 0x14, 0x4c, 0x69,
0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x22,
0x40, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b,
0x66, 0x6c, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x57, 0x6f,
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
0x73, 0x22, 0x58, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
0x77, 0x73, 0x46, 0x6f, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1b,
0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x22, 0xaf, 0x02, 0x0a, 0x08,
0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61,
0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61,
0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x49, 0x0a, 0x12, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x69,
0x67, 0x67, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x11, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
0x65, 0x64, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x12, 0x2a, 0x0a, 0x04, 0x6a, 0x6f,
0x62, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4a, 0x6f, 0x62, 0x4f, 0x70, 0x74, 0x73,
0x52, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4a, 0x6f, 0x62, 0x4f, 0x70, 0x74, 0x73,
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75,
0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x17, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
0x53, 0x74, 0x65, 0x70, 0x4f, 0x70, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x22,
0x83, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
0x6f, 0x77, 0x53, 0x74, 0x65, 0x70, 0x4f, 0x70, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65,
0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0a, 0x72, 0x65, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x0a,
0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69,
0x6e, 0x70, 0x75, 0x74, 0x73, 0x22, 0x33, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72,
0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a,
0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x91, 0x01, 0x0a, 0x17, 0x53,
0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74,
0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e,
0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f,
0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
0x6f, 0x77, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x09, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1b,
0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
0x3e, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c,
0x75, 0x65, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12,
0x2c, 0x0a, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xb1, 0x02,
0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a,
0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70,
0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05,
0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66,
0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f,
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x08, 0x74, 0x72, 0x69, 0x67,
0x67, 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x57, 0x6f, 0x72,
0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x52, 0x08, 0x74,
0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x18,
0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x04, 0x6a, 0x6f, 0x62,
0x73, 0x22, 0xc6, 0x02, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72,
0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41,
0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2e, 0x0a, 0x13,
0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66,
0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09,
0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x06, 0x65, 0x76, 0x65,
0x6e, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x57, 0x6f, 0x72, 0x6b,
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74,
0x52, 0x65, 0x66, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2d, 0x0a, 0x05, 0x63,
0x72, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x57, 0x6f, 0x72,
0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x72, 0x6f, 0x6e,
0x52, 0x65, 0x66, 0x52, 0x05, 0x63, 0x72, 0x6f, 0x6e, 0x73, 0x22, 0x53, 0x0a, 0x17, 0x57, 0x6f,
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f,
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x22,
0x49, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67,
0x65, 0x72, 0x43, 0x72, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72,
0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61,
0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x22, 0x81, 0x03, 0x0a, 0x03, 0x4a,
0x6f, 0x62, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a,
0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75,
0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61,
0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e,
0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
0x77, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01,
0x28, 0x09, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x64, 0x65, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0b, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x05, 0x73, 0x74, 0x65,
0x70, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x53, 0x74, 0x65, 0x70, 0x52,
0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x12, 0x36, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75,
0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0xe8,
0x02, 0x0a, 0x04, 0x53, 0x74, 0x65, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x40,
0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66,
0x6c, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x57, 0x6f, 0x72,
0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73,
0x22, 0x58, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
0x73, 0x46, 0x6f, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a,
0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x22, 0xaf, 0x02, 0x0a, 0x08, 0x57,
0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74,
0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69,
@@ -1364,57 +1356,154 @@ var file_workflows_proto_rawDesc = []byte{
0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x3d, 0x0a,
0x0b, 0x72, 0x65, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65,
0x52, 0x0a, 0x72, 0x65, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09,
0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62,
0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64,
0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65,
0x6f, 0x75, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69,
0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
0x12, 0x17, 0x0a, 0x07, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28,
0x09, 0x52, 0x06, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x64, 0x22, 0x55, 0x0a, 0x15, 0x44, 0x65, 0x6c,
0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12,
0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64,
0x22, 0x4b, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x42,
0x79, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09,
0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x32, 0xc7, 0x02,
0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
0x77, 0x73, 0x12, 0x15, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1b, 0x0a,
0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e,
0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75,
0x65, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c,
0x0a, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xb1, 0x02, 0x0a,
0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75,
0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64,
0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52,
0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72,
0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x08, 0x74, 0x72, 0x69, 0x67, 0x67,
0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x57, 0x6f, 0x72, 0x6b,
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x52, 0x08, 0x74, 0x72,
0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x18, 0x09,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x04, 0x6a, 0x6f, 0x62, 0x73,
0x22, 0xc6, 0x02, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69,
0x67, 0x67, 0x65, 0x72, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74,
0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x77,
0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74,
0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e,
0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66,
0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52,
0x65, 0x66, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2d, 0x0a, 0x05, 0x63, 0x72,
0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x57, 0x6f, 0x72, 0x6b,
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x72, 0x6f, 0x6e, 0x52,
0x65, 0x66, 0x52, 0x05, 0x63, 0x72, 0x6f, 0x6e, 0x73, 0x22, 0x53, 0x0a, 0x17, 0x57, 0x6f, 0x72,
0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e,
0x74, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49,
0x64, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x49,
0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65,
0x72, 0x43, 0x72, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65,
0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x72,
0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x72, 0x6f, 0x6e, 0x22, 0x81, 0x03, 0x0a, 0x03, 0x4a, 0x6f,
0x62, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a,
0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70,
0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e,
0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61,
0x6e, 0x74, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
0x09, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0b, 0x64, 0x65, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x05, 0x73, 0x74, 0x65, 0x70,
0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x53, 0x74, 0x65, 0x70, 0x52, 0x05,
0x73, 0x74, 0x65, 0x70, 0x73, 0x12, 0x36, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56,
0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0xe8, 0x02,
0x0a, 0x04, 0x53, 0x74, 0x65, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41,
0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x3d, 0x0a, 0x0b,
0x72, 0x65, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
0x0a, 0x72, 0x65, 0x61, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74,
0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f,
0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12,
0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f,
0x75, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e,
0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12,
0x17, 0x0a, 0x07, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x64, 0x22, 0x55, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65,
0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1f,
0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x22,
0x4b, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x42, 0x79,
0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74,
0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x32, 0x87, 0x03, 0x0a,
0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x12, 0x3e, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
0x73, 0x12, 0x15, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57,
0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x34, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12,
0x13, 0x2e, 0x50, 0x75, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x10, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75,
0x6c, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x2e, 0x53, 0x63, 0x68,
0x65, 0x64, 0x75, 0x6c, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x56,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72,
0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x2e, 0x47, 0x65,
0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x09, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
0x77, 0x12, 0x4e, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
0x77, 0x73, 0x46, 0x6f, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x2e, 0x4c, 0x69, 0x73,
0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x46, 0x6f, 0x72, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x34, 0x0a, 0x0b, 0x50, 0x75, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
0x12, 0x13, 0x2e, 0x50, 0x75, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x57, 0x6f,
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x2e, 0x47,
0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x42, 0x79, 0x4e, 0x61, 0x6d, 0x65,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x09, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
0x6f, 0x77, 0x12, 0x4e, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
0x6f, 0x77, 0x73, 0x46, 0x6f, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x2e, 0x4c, 0x69,
0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x46, 0x6f, 0x72, 0x45, 0x76,
0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x4c, 0x69, 0x73,
0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x33, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b,
0x66, 0x6c, 0x6f, 0x77, 0x12, 0x16, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72,
0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x09, 0x2e, 0x57,
0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2d, 0x64, 0x65,
0x76, 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x64, 0x6d, 0x69,
0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
0x65, 0x12, 0x33, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66,
0x6c, 0x6f, 0x77, 0x12, 0x16, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b,
0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x09, 0x2e, 0x57, 0x6f,
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2d, 0x64, 0x65, 0x76,
0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x64, 0x6d, 0x69, 0x6e,
0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
@@ -1429,68 +1518,73 @@ func file_workflows_proto_rawDescGZIP() []byte {
return file_workflows_proto_rawDescData
}
var file_workflows_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
var file_workflows_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
var file_workflows_proto_goTypes = []interface{}{
(*PutWorkflowRequest)(nil), // 0: PutWorkflowRequest
(*CreateWorkflowVersionOpts)(nil), // 1: CreateWorkflowVersionOpts
(*CreateWorkflowJobOpts)(nil), // 2: CreateWorkflowJobOpts
(*CreateWorkflowStepOpts)(nil), // 3: CreateWorkflowStepOpts
(*ListWorkflowsRequest)(nil), // 4: ListWorkflowsRequest
(*ListWorkflowsResponse)(nil), // 5: ListWorkflowsResponse
(*ListWorkflowsForEventRequest)(nil), // 6: ListWorkflowsForEventRequest
(*Workflow)(nil), // 7: Workflow
(*WorkflowVersion)(nil), // 8: WorkflowVersion
(*WorkflowTriggers)(nil), // 9: WorkflowTriggers
(*WorkflowTriggerEventRef)(nil), // 10: WorkflowTriggerEventRef
(*WorkflowTriggerCronRef)(nil), // 11: WorkflowTriggerCronRef
(*Job)(nil), // 12: Job
(*Step)(nil), // 13: Step
(*DeleteWorkflowRequest)(nil), // 14: DeleteWorkflowRequest
(*GetWorkflowByNameRequest)(nil), // 15: GetWorkflowByNameRequest
(*timestamppb.Timestamp)(nil), // 16: google.protobuf.Timestamp
(*wrapperspb.StringValue)(nil), // 17: google.protobuf.StringValue
(*ScheduleWorkflowRequest)(nil), // 5: ScheduleWorkflowRequest
(*ListWorkflowsResponse)(nil), // 6: ListWorkflowsResponse
(*ListWorkflowsForEventRequest)(nil), // 7: ListWorkflowsForEventRequest
(*Workflow)(nil), // 8: Workflow
(*WorkflowVersion)(nil), // 9: WorkflowVersion
(*WorkflowTriggers)(nil), // 10: WorkflowTriggers
(*WorkflowTriggerEventRef)(nil), // 11: WorkflowTriggerEventRef
(*WorkflowTriggerCronRef)(nil), // 12: WorkflowTriggerCronRef
(*Job)(nil), // 13: Job
(*Step)(nil), // 14: Step
(*DeleteWorkflowRequest)(nil), // 15: DeleteWorkflowRequest
(*GetWorkflowByNameRequest)(nil), // 16: GetWorkflowByNameRequest
(*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp
(*wrapperspb.StringValue)(nil), // 18: google.protobuf.StringValue
}
var file_workflows_proto_depIdxs = []int32{
1, // 0: PutWorkflowRequest.opts:type_name -> CreateWorkflowVersionOpts
2, // 1: CreateWorkflowVersionOpts.jobs:type_name -> CreateWorkflowJobOpts
3, // 2: CreateWorkflowJobOpts.steps:type_name -> CreateWorkflowStepOpts
7, // 3: ListWorkflowsResponse.workflows:type_name -> Workflow
16, // 4: Workflow.created_at:type_name -> google.protobuf.Timestamp
16, // 5: Workflow.updated_at:type_name -> google.protobuf.Timestamp
17, // 6: Workflow.description:type_name -> google.protobuf.StringValue
8, // 7: Workflow.versions:type_name -> WorkflowVersion
16, // 8: WorkflowVersion.created_at:type_name -> google.protobuf.Timestamp
16, // 9: WorkflowVersion.updated_at:type_name -> google.protobuf.Timestamp
9, // 10: WorkflowVersion.triggers:type_name -> WorkflowTriggers
12, // 11: WorkflowVersion.jobs:type_name -> Job
16, // 12: WorkflowTriggers.created_at:type_name -> google.protobuf.Timestamp
16, // 13: WorkflowTriggers.updated_at:type_name -> google.protobuf.Timestamp
10, // 14: WorkflowTriggers.events:type_name -> WorkflowTriggerEventRef
11, // 15: WorkflowTriggers.crons:type_name -> WorkflowTriggerCronRef
16, // 16: Job.created_at:type_name -> google.protobuf.Timestamp
16, // 17: Job.updated_at:type_name -> google.protobuf.Timestamp
17, // 18: Job.description:type_name -> google.protobuf.StringValue
13, // 19: Job.steps:type_name -> Step
17, // 20: Job.timeout:type_name -> google.protobuf.StringValue
16, // 21: Step.created_at:type_name -> google.protobuf.Timestamp
16, // 22: Step.updated_at:type_name -> google.protobuf.Timestamp
17, // 23: Step.readable_id:type_name -> google.protobuf.StringValue
17, // 24: Step.timeout:type_name -> google.protobuf.StringValue
4, // 25: WorkflowService.ListWorkflows:input_type -> ListWorkflowsRequest
0, // 26: WorkflowService.PutWorkflow:input_type -> PutWorkflowRequest
15, // 27: WorkflowService.GetWorkflowByName:input_type -> GetWorkflowByNameRequest
6, // 28: WorkflowService.ListWorkflowsForEvent:input_type -> ListWorkflowsForEventRequest
14, // 29: WorkflowService.DeleteWorkflow:input_type -> DeleteWorkflowRequest
5, // 30: WorkflowService.ListWorkflows:output_type -> ListWorkflowsResponse
8, // 31: WorkflowService.PutWorkflow:output_type -> WorkflowVersion
7, // 32: WorkflowService.GetWorkflowByName:output_type -> Workflow
5, // 33: WorkflowService.ListWorkflowsForEvent:output_type -> ListWorkflowsResponse
7, // 34: WorkflowService.DeleteWorkflow:output_type -> Workflow
30, // [30:35] is the sub-list for method output_type
25, // [25:30] is the sub-list for method input_type
25, // [25:25] is the sub-list for extension type_name
25, // [25:25] is the sub-list for extension extendee
0, // [0:25] is the sub-list for field type_name
17, // 1: CreateWorkflowVersionOpts.scheduled_triggers:type_name -> google.protobuf.Timestamp
2, // 2: CreateWorkflowVersionOpts.jobs:type_name -> CreateWorkflowJobOpts
3, // 3: CreateWorkflowJobOpts.steps:type_name -> CreateWorkflowStepOpts
17, // 4: ScheduleWorkflowRequest.schedules:type_name -> google.protobuf.Timestamp
8, // 5: ListWorkflowsResponse.workflows:type_name -> Workflow
17, // 6: Workflow.created_at:type_name -> google.protobuf.Timestamp
17, // 7: Workflow.updated_at:type_name -> google.protobuf.Timestamp
18, // 8: Workflow.description:type_name -> google.protobuf.StringValue
9, // 9: Workflow.versions:type_name -> WorkflowVersion
17, // 10: WorkflowVersion.created_at:type_name -> google.protobuf.Timestamp
17, // 11: WorkflowVersion.updated_at:type_name -> google.protobuf.Timestamp
10, // 12: WorkflowVersion.triggers:type_name -> WorkflowTriggers
13, // 13: WorkflowVersion.jobs:type_name -> Job
17, // 14: WorkflowTriggers.created_at:type_name -> google.protobuf.Timestamp
17, // 15: WorkflowTriggers.updated_at:type_name -> google.protobuf.Timestamp
11, // 16: WorkflowTriggers.events:type_name -> WorkflowTriggerEventRef
12, // 17: WorkflowTriggers.crons:type_name -> WorkflowTriggerCronRef
17, // 18: Job.created_at:type_name -> google.protobuf.Timestamp
17, // 19: Job.updated_at:type_name -> google.protobuf.Timestamp
18, // 20: Job.description:type_name -> google.protobuf.StringValue
14, // 21: Job.steps:type_name -> Step
18, // 22: Job.timeout:type_name -> google.protobuf.StringValue
17, // 23: Step.created_at:type_name -> google.protobuf.Timestamp
17, // 24: Step.updated_at:type_name -> google.protobuf.Timestamp
18, // 25: Step.readable_id:type_name -> google.protobuf.StringValue
18, // 26: Step.timeout:type_name -> google.protobuf.StringValue
4, // 27: WorkflowService.ListWorkflows:input_type -> ListWorkflowsRequest
0, // 28: WorkflowService.PutWorkflow:input_type -> PutWorkflowRequest
5, // 29: WorkflowService.ScheduleWorkflow:input_type -> ScheduleWorkflowRequest
16, // 30: WorkflowService.GetWorkflowByName:input_type -> GetWorkflowByNameRequest
7, // 31: WorkflowService.ListWorkflowsForEvent:input_type -> ListWorkflowsForEventRequest
15, // 32: WorkflowService.DeleteWorkflow:input_type -> DeleteWorkflowRequest
6, // 33: WorkflowService.ListWorkflows:output_type -> ListWorkflowsResponse
9, // 34: WorkflowService.PutWorkflow:output_type -> WorkflowVersion
9, // 35: WorkflowService.ScheduleWorkflow:output_type -> WorkflowVersion
8, // 36: WorkflowService.GetWorkflowByName:output_type -> Workflow
6, // 37: WorkflowService.ListWorkflowsForEvent:output_type -> ListWorkflowsResponse
8, // 38: WorkflowService.DeleteWorkflow:output_type -> Workflow
33, // [33:39] is the sub-list for method output_type
27, // [27:33] is the sub-list for method input_type
27, // [27:27] is the sub-list for extension type_name
27, // [27:27] is the sub-list for extension extendee
0, // [0:27] is the sub-list for field type_name
}
func init() { file_workflows_proto_init() }
@@ -1560,7 +1654,7 @@ func file_workflows_proto_init() {
}
}
file_workflows_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListWorkflowsResponse); i {
switch v := v.(*ScheduleWorkflowRequest); i {
case 0:
return &v.state
case 1:
@@ -1572,7 +1666,7 @@ func file_workflows_proto_init() {
}
}
file_workflows_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListWorkflowsForEventRequest); i {
switch v := v.(*ListWorkflowsResponse); i {
case 0:
return &v.state
case 1:
@@ -1584,7 +1678,7 @@ func file_workflows_proto_init() {
}
}
file_workflows_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Workflow); i {
switch v := v.(*ListWorkflowsForEventRequest); i {
case 0:
return &v.state
case 1:
@@ -1596,7 +1690,7 @@ func file_workflows_proto_init() {
}
}
file_workflows_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*WorkflowVersion); i {
switch v := v.(*Workflow); i {
case 0:
return &v.state
case 1:
@@ -1608,7 +1702,7 @@ func file_workflows_proto_init() {
}
}
file_workflows_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*WorkflowTriggers); i {
switch v := v.(*WorkflowVersion); i {
case 0:
return &v.state
case 1:
@@ -1620,7 +1714,7 @@ func file_workflows_proto_init() {
}
}
file_workflows_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*WorkflowTriggerEventRef); i {
switch v := v.(*WorkflowTriggers); i {
case 0:
return &v.state
case 1:
@@ -1632,7 +1726,7 @@ func file_workflows_proto_init() {
}
}
file_workflows_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*WorkflowTriggerCronRef); i {
switch v := v.(*WorkflowTriggerEventRef); i {
case 0:
return &v.state
case 1:
@@ -1644,7 +1738,7 @@ func file_workflows_proto_init() {
}
}
file_workflows_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Job); i {
switch v := v.(*WorkflowTriggerCronRef); i {
case 0:
return &v.state
case 1:
@@ -1656,7 +1750,7 @@ func file_workflows_proto_init() {
}
}
file_workflows_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Step); i {
switch v := v.(*Job); i {
case 0:
return &v.state
case 1:
@@ -1668,7 +1762,7 @@ func file_workflows_proto_init() {
}
}
file_workflows_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteWorkflowRequest); i {
switch v := v.(*Step); i {
case 0:
return &v.state
case 1:
@@ -1680,6 +1774,18 @@ func file_workflows_proto_init() {
}
}
file_workflows_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteWorkflowRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_workflows_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetWorkflowByNameRequest); i {
case 0:
return &v.state
@@ -1698,7 +1804,7 @@ func file_workflows_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_workflows_proto_rawDesc,
NumEnums: 0,
NumMessages: 16,
NumMessages: 17,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -24,6 +24,7 @@ const _ = grpc.SupportPackageIsVersion7
type WorkflowServiceClient interface {
ListWorkflows(ctx context.Context, in *ListWorkflowsRequest, opts ...grpc.CallOption) (*ListWorkflowsResponse, error)
PutWorkflow(ctx context.Context, in *PutWorkflowRequest, opts ...grpc.CallOption) (*WorkflowVersion, error)
ScheduleWorkflow(ctx context.Context, in *ScheduleWorkflowRequest, opts ...grpc.CallOption) (*WorkflowVersion, error)
GetWorkflowByName(ctx context.Context, in *GetWorkflowByNameRequest, opts ...grpc.CallOption) (*Workflow, error)
ListWorkflowsForEvent(ctx context.Context, in *ListWorkflowsForEventRequest, opts ...grpc.CallOption) (*ListWorkflowsResponse, error)
DeleteWorkflow(ctx context.Context, in *DeleteWorkflowRequest, opts ...grpc.CallOption) (*Workflow, error)
@@ -55,6 +56,15 @@ func (c *workflowServiceClient) PutWorkflow(ctx context.Context, in *PutWorkflow
return out, nil
}
func (c *workflowServiceClient) ScheduleWorkflow(ctx context.Context, in *ScheduleWorkflowRequest, opts ...grpc.CallOption) (*WorkflowVersion, error) {
out := new(WorkflowVersion)
err := c.cc.Invoke(ctx, "/WorkflowService/ScheduleWorkflow", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *workflowServiceClient) GetWorkflowByName(ctx context.Context, in *GetWorkflowByNameRequest, opts ...grpc.CallOption) (*Workflow, error) {
out := new(Workflow)
err := c.cc.Invoke(ctx, "/WorkflowService/GetWorkflowByName", in, out, opts...)
@@ -88,6 +98,7 @@ func (c *workflowServiceClient) DeleteWorkflow(ctx context.Context, in *DeleteWo
type WorkflowServiceServer interface {
ListWorkflows(context.Context, *ListWorkflowsRequest) (*ListWorkflowsResponse, error)
PutWorkflow(context.Context, *PutWorkflowRequest) (*WorkflowVersion, error)
ScheduleWorkflow(context.Context, *ScheduleWorkflowRequest) (*WorkflowVersion, error)
GetWorkflowByName(context.Context, *GetWorkflowByNameRequest) (*Workflow, error)
ListWorkflowsForEvent(context.Context, *ListWorkflowsForEventRequest) (*ListWorkflowsResponse, error)
DeleteWorkflow(context.Context, *DeleteWorkflowRequest) (*Workflow, error)
@@ -104,6 +115,9 @@ func (UnimplementedWorkflowServiceServer) ListWorkflows(context.Context, *ListWo
func (UnimplementedWorkflowServiceServer) PutWorkflow(context.Context, *PutWorkflowRequest) (*WorkflowVersion, error) {
return nil, status.Errorf(codes.Unimplemented, "method PutWorkflow not implemented")
}
func (UnimplementedWorkflowServiceServer) ScheduleWorkflow(context.Context, *ScheduleWorkflowRequest) (*WorkflowVersion, error) {
return nil, status.Errorf(codes.Unimplemented, "method ScheduleWorkflow not implemented")
}
func (UnimplementedWorkflowServiceServer) GetWorkflowByName(context.Context, *GetWorkflowByNameRequest) (*Workflow, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetWorkflowByName not implemented")
}
@@ -162,6 +176,24 @@ func _WorkflowService_PutWorkflow_Handler(srv interface{}, ctx context.Context,
return interceptor(ctx, in, info, handler)
}
func _WorkflowService_ScheduleWorkflow_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ScheduleWorkflowRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WorkflowServiceServer).ScheduleWorkflow(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/WorkflowService/ScheduleWorkflow",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WorkflowServiceServer).ScheduleWorkflow(ctx, req.(*ScheduleWorkflowRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WorkflowService_GetWorkflowByName_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetWorkflowByNameRequest)
if err := dec(in); err != nil {
@@ -231,6 +263,10 @@ var WorkflowService_ServiceDesc = grpc.ServiceDesc{
MethodName: "PutWorkflow",
Handler: _WorkflowService_PutWorkflow_Handler,
},
{
MethodName: "ScheduleWorkflow",
Handler: _WorkflowService_ScheduleWorkflow_Handler,
},
{
MethodName: "GetWorkflowByName",
Handler: _WorkflowService_GetWorkflowByName_Handler,

View File

@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"errors"
"fmt"
"time"
"github.com/hatchet-dev/hatchet/internal/datautils"
@@ -148,6 +149,58 @@ func (a *AdminServiceImpl) PutWorkflow(ctx context.Context, req *contracts.PutWo
}
}
if schedules := workflowVersion.Scheduled(); len(schedules) > 0 {
within := time.Now().UTC().Add(-6 * time.Second)
tickers, err := a.repo.Ticker().ListTickers(&repository.ListTickerOpts{
LatestHeartbeatAt: &within,
})
if err != nil {
return nil, err
}
if len(tickers) == 0 {
return nil, status.Error(
codes.FailedPrecondition,
"no tickers available",
)
}
numTickers := len(tickers)
for i, scheduledTrigger := range schedules {
scheduledTriggerCp := scheduledTrigger
ticker := tickers[i%numTickers]
_, err := a.repo.Ticker().AddScheduledWorkflow(
ticker.ID,
&scheduledTriggerCp,
)
if err != nil {
return nil, err
}
task, err := workflowScheduleTask(&ticker, &scheduledTriggerCp, workflowVersion)
if err != nil {
return nil, err
}
// send to task queue
err = a.tq.AddTask(
ctx,
taskqueue.QueueTypeFromTicker(&ticker),
task,
)
if err != nil {
return nil, err
}
}
}
// cancel the old workflow version
if oldWorkflowVersion != nil {
oldTriggers, ok := oldWorkflowVersion.Triggers()
@@ -193,6 +246,148 @@ func (a *AdminServiceImpl) PutWorkflow(ctx context.Context, req *contracts.PutWo
}
}
}
if schedules := oldWorkflowVersion.Scheduled(); len(schedules) > 0 {
for _, scheduleTrigger := range schedules {
scheduleTriggerCp := scheduleTrigger
if ticker, ok := scheduleTriggerCp.Ticker(); ok {
task, err := workflowCancelTask(ticker, &scheduleTriggerCp, workflowVersion)
if err != nil {
return nil, err
}
// only send to task queue if the trigger is in the future
if scheduleTriggerCp.TriggerAt.After(time.Now().UTC()) {
err = a.tq.AddTask(
ctx,
taskqueue.QueueTypeFromTicker(ticker),
task,
)
if err != nil {
return nil, err
}
// remove cron
_, err = a.repo.Ticker().RemoveScheduledWorkflow(
ticker.ID,
&scheduleTrigger,
)
if err != nil {
return nil, err
}
}
}
}
}
}
resp := toWorkflowVersion(workflowVersion)
return resp, nil
}
func (a *AdminServiceImpl) ScheduleWorkflow(ctx context.Context, req *contracts.ScheduleWorkflowRequest) (*contracts.WorkflowVersion, error) {
// TODO: authorize request
currWorkflow, err := a.repo.Workflow().GetWorkflowById(
req.WorkflowId,
)
if err != nil {
if !errors.Is(err, db.ErrNotFound) {
return nil, fmt.Errorf("workflow with id %s does not exist", req.WorkflowId)
}
return nil, err
}
workflowVersion := &currWorkflow.Versions()[0]
if workflowVersion == nil {
return nil, fmt.Errorf("workflow with id %s has no versions", req.WorkflowId)
}
dbSchedules := make([]time.Time, len(req.Schedules))
for _, scheduledTrigger := range req.Schedules {
dbSchedules = append(dbSchedules, scheduledTrigger.AsTime())
}
schedules, err := a.repo.Workflow().CreateSchedules(
req.TenantId,
workflowVersion.ID,
&repository.CreateWorkflowSchedulesOpts{
ScheduledTriggers: dbSchedules,
},
)
if err != nil {
return nil, err
}
if len(schedules) > 0 {
within := time.Now().UTC().Add(-6 * time.Second)
tickers, err := a.repo.Ticker().ListTickers(&repository.ListTickerOpts{
LatestHeartbeatAt: &within,
})
if err != nil {
return nil, err
}
if len(tickers) == 0 {
return nil, status.Error(
codes.FailedPrecondition,
"no tickers available",
)
}
numTickers := len(tickers)
for i, scheduledTrigger := range schedules {
scheduledTriggerCp := scheduledTrigger
ticker := tickers[i%numTickers]
_, err := a.repo.Ticker().AddScheduledWorkflow(
ticker.ID,
scheduledTriggerCp,
)
if err != nil {
return nil, err
}
task, err := workflowScheduleTask(&ticker, scheduledTriggerCp, workflowVersion)
if err != nil {
return nil, err
}
// send to task queue
err = a.tq.AddTask(
ctx,
taskqueue.QueueTypeFromTicker(&ticker),
task,
)
if err != nil {
return nil, err
}
}
}
workflowVersion, err = a.repo.Workflow().GetWorkflowVersionById(
currWorkflow.TenantID,
workflowVersion.ID,
)
if err != nil {
return nil, err
}
resp := toWorkflowVersion(workflowVersion)
@@ -306,13 +501,20 @@ func getCreateWorkflowOpts(req *contracts.PutWorkflowRequest) (*repository.Creat
}
}
scheduledTriggers := make([]time.Time, 0)
for _, trigger := range req.Opts.ScheduledTriggers {
scheduledTriggers = append(scheduledTriggers, trigger.AsTime())
}
return &repository.CreateWorkflowVersionOpts{
Name: req.Opts.Name,
Description: &req.Opts.Description,
Version: req.Opts.Version,
EventTriggers: req.Opts.EventTriggers,
CronTriggers: req.Opts.CronTriggers,
Jobs: jobs,
Name: req.Opts.Name,
Description: &req.Opts.Description,
Version: req.Opts.Version,
EventTriggers: req.Opts.EventTriggers,
CronTriggers: req.Opts.CronTriggers,
ScheduledTriggers: scheduledTriggers,
Jobs: jobs,
}, nil
}
@@ -499,3 +701,41 @@ func cronCancelTask(ticker *db.TickerModel, cronTriggerRef *db.WorkflowTriggerCr
Metadata: metadata,
}, nil
}
func workflowScheduleTask(ticker *db.TickerModel, workflowTriggerRef *db.WorkflowTriggerScheduledRefModel, workflowVersion *db.WorkflowVersionModel) (*taskqueue.Task, error) {
payload, _ := datautils.ToJSONMap(tasktypes.ScheduleWorkflowTaskPayload{
ScheduledWorkflowId: workflowTriggerRef.ID,
TriggerAt: workflowTriggerRef.TriggerAt.Format(time.RFC3339),
WorkflowVersionId: workflowVersion.ID,
})
metadata, _ := datautils.ToJSONMap(tasktypes.ScheduleWorkflowTaskMetadata{
TenantId: workflowVersion.Workflow().TenantID,
})
return &taskqueue.Task{
ID: "schedule-workflow",
Queue: taskqueue.QueueTypeFromTicker(ticker),
Payload: payload,
Metadata: metadata,
}, nil
}
func workflowCancelTask(ticker *db.TickerModel, workflowTriggerRef *db.WorkflowTriggerScheduledRefModel, workflowVersion *db.WorkflowVersionModel) (*taskqueue.Task, error) {
payload, _ := datautils.ToJSONMap(tasktypes.CancelWorkflowTaskPayload{
ScheduledWorkflowId: workflowTriggerRef.ID,
TriggerAt: workflowTriggerRef.TriggerAt.Format(time.RFC3339),
WorkflowVersionId: workflowVersion.ID,
})
metadata, _ := datautils.ToJSONMap(tasktypes.CancelWorkflowTaskMetadata{
TenantId: workflowVersion.Workflow().TenantID,
})
return &taskqueue.Task{
ID: "cancel-workflow",
Queue: taskqueue.QueueTypeFromTicker(ticker),
Payload: payload,
Metadata: metadata,
}, nil
}

View File

@@ -7,7 +7,7 @@ import (
"sync"
"time"
"github.com/go-co-op/gocron"
"github.com/go-co-op/gocron/v2"
"github.com/google/uuid"
"github.com/hatchet-dev/hatchet/internal/datautils"
"github.com/hatchet-dev/hatchet/internal/repository"
@@ -25,7 +25,7 @@ type Dispatcher interface {
type DispatcherImpl struct {
contracts.UnimplementedDispatcherServer
s *gocron.Scheduler
s gocron.Scheduler
tq taskqueue.TaskQueue
l *zerolog.Logger
dv datautils.DataDecoderValidator
@@ -98,7 +98,12 @@ func New(fs ...DispatcherOpt) (*DispatcherImpl, error) {
return nil, fmt.Errorf("repository is required. use WithRepository")
}
s := gocron.NewScheduler(time.UTC)
// create a new scheduler
s, err := gocron.NewScheduler(gocron.WithLocation(time.UTC))
if err != nil {
return nil, fmt.Errorf("could not create scheduler for dispatcher: %w", err)
}
return &DispatcherImpl{
tq: opts.tq,
@@ -128,13 +133,18 @@ func (d *DispatcherImpl) Start(ctx context.Context) error {
return err
}
_, err = d.s.Every(5).Seconds().Do(d.runUpdateHeartbeat(ctx))
_, err = d.s.NewJob(
gocron.DurationJob(time.Second*5),
gocron.NewTask(
d.runUpdateHeartbeat(ctx),
),
)
if err != nil {
return fmt.Errorf("could not schedule heartbeat update: %w", err)
}
d.s.StartAsync()
d.s.Start()
for {
select {

View File

@@ -44,6 +44,26 @@ type CancelCronTaskMetadata struct {
TenantId string `json:"tenant_id" validate:"required,uuid"`
}
type ScheduleWorkflowTaskPayload struct {
ScheduledWorkflowId string `json:"scheduled_workflow_id" validate:"required,uuid"`
TriggerAt string `json:"trigger_at" validate:"required"`
WorkflowVersionId string `json:"workflow_version_id" validate:"required,uuid"`
}
type ScheduleWorkflowTaskMetadata struct {
TenantId string `json:"tenant_id" validate:"required,uuid"`
}
type CancelWorkflowTaskPayload struct {
ScheduledWorkflowId string `json:"scheduled_workflow_id" validate:"required,uuid"`
TriggerAt string `json:"trigger_at" validate:"required"`
WorkflowVersionId string `json:"workflow_version_id" validate:"required,uuid"`
}
type CancelWorkflowTaskMetadata struct {
TenantId string `json:"tenant_id" validate:"required,uuid"`
}
type ScheduleJobRunTimeoutTaskPayload struct {
JobRunId string `json:"job_run_id" validate:"required,uuid"`
TimeoutAt string `json:"timeout_at" validate:"required"`

View File

@@ -5,7 +5,7 @@ import (
"fmt"
"time"
"github.com/go-co-op/gocron"
"github.com/go-co-op/gocron/v2"
"github.com/hatchet-dev/hatchet/internal/repository"
"github.com/hatchet-dev/hatchet/internal/repository/prisma/db"
"github.com/hatchet-dev/hatchet/internal/services/shared/tasktypes"
@@ -37,24 +37,33 @@ func (t *TickerImpl) handleScheduleCron(ctx context.Context, task *taskqueue.Tas
}
// create a new scheduler
s := gocron.NewScheduler(time.UTC)
s, err := gocron.NewScheduler(gocron.WithLocation(time.UTC))
if err != nil {
return fmt.Errorf("could not create scheduler: %w", err)
}
// schedule the cron
_, err = s.Cron(payload.Cron).Do(t.runWorkflow(ctx, metadata.TenantId, &payload, workflowVersion))
_, err = t.s.NewJob(
gocron.CronJob(payload.Cron, false),
gocron.NewTask(
t.runCronWorkflow(ctx, metadata.TenantId, &payload, workflowVersion),
),
)
if err != nil {
return fmt.Errorf("could not schedule cron: %w", err)
}
// store the schedule in the cron map
t.crons.Store(payload.WorkflowVersionId, s)
t.crons.Store(getCronKey(payload.WorkflowVersionId, payload.Cron), s)
s.StartAsync()
s.Start()
return nil
}
func (t *TickerImpl) runWorkflow(ctx context.Context, tenantId string, payload *tasktypes.ScheduleCronTaskPayload, workflowVersion *db.WorkflowVersionModel) func() {
func (t *TickerImpl) runCronWorkflow(ctx context.Context, tenantId string, payload *tasktypes.ScheduleCronTaskPayload, workflowVersion *db.WorkflowVersionModel) func() {
return func() {
t.l.Debug().Msgf("ticker: running workflow %s", payload.WorkflowVersionId)
@@ -108,16 +117,22 @@ func (t *TickerImpl) handleCancelCron(ctx context.Context, task *taskqueue.Task)
}
// get the scheduler
schedulerVal, ok := t.crons.Load(payload.WorkflowVersionId)
schedulerVal, ok := t.crons.Load(getCronKey(payload.WorkflowVersionId, payload.Cron))
if !ok {
return fmt.Errorf("could not find cron %s", payload.WorkflowVersionId)
return fmt.Errorf("could not find cron %s with schedule %s", payload.WorkflowVersionId, payload.Cron)
}
scheduler := schedulerVal.(*gocron.Scheduler)
defer t.crons.Delete(getCronKey(payload.WorkflowVersionId, payload.Cron))
scheduler := schedulerVal.(gocron.Scheduler)
// cancel the cron
scheduler.Clear()
scheduler.Shutdown()
return nil
}
func getCronKey(workflowVersionId, schedule string) string {
return fmt.Sprintf("%s-%s", workflowVersionId, schedule)
}

View File

@@ -0,0 +1,167 @@
package ticker
import (
"context"
"fmt"
"time"
"github.com/go-co-op/gocron/v2"
"github.com/hatchet-dev/hatchet/internal/repository"
"github.com/hatchet-dev/hatchet/internal/repository/prisma/db"
"github.com/hatchet-dev/hatchet/internal/services/shared/tasktypes"
"github.com/hatchet-dev/hatchet/internal/taskqueue"
)
func (t *TickerImpl) handleScheduleWorkflow(ctx context.Context, task *taskqueue.Task) error {
t.l.Debug().Msg("ticker: scheduling workflow")
payload := tasktypes.ScheduleWorkflowTaskPayload{}
metadata := tasktypes.ScheduleWorkflowTaskMetadata{}
err := t.dv.DecodeAndValidate(task.Payload, &payload)
if err != nil {
return fmt.Errorf("could not decode ticker task payload: %w", err)
}
err = t.dv.DecodeAndValidate(task.Metadata, &metadata)
if err != nil {
return fmt.Errorf("could not decode ticker task metadata: %w", err)
}
workflowVersion, err := t.repo.Workflow().GetWorkflowVersionById(metadata.TenantId, payload.WorkflowVersionId)
if err != nil {
return fmt.Errorf("could not get workflow version: %w", err)
}
// create a new scheduler
s, err := gocron.NewScheduler(gocron.WithLocation(time.UTC))
if err != nil {
return fmt.Errorf("could not create scheduler: %w", err)
}
// parse trigger time
triggerAt, err := time.Parse(time.RFC3339, payload.TriggerAt)
if err != nil {
return fmt.Errorf("could not parse started at: %w", err)
}
// schedule the workflow
_, err = t.s.NewJob(
gocron.OneTimeJob(
gocron.OneTimeJobStartDateTime(triggerAt),
),
gocron.NewTask(
t.runScheduledWorkflow(ctx, metadata.TenantId, payload.ScheduledWorkflowId, workflowVersion),
),
)
if err != nil {
return fmt.Errorf("could not schedule workflow: %w", err)
}
// store the schedule in the cron map
t.scheduledWorkflows.Store(getScheduledWorkflowKey(workflowVersion.ID, payload.ScheduledWorkflowId), s)
s.Start()
return nil
}
func (t *TickerImpl) runScheduledWorkflow(ctx context.Context, tenantId, scheduledWorkflowId string, workflowVersion *db.WorkflowVersionModel) func() {
return func() {
t.l.Debug().Msgf("ticker: running workflow %s", workflowVersion.ID)
// create a new workflow run in the database
createOpts, err := repository.GetCreateWorkflowRunOptsFromSchedule(scheduledWorkflowId, workflowVersion)
if err != nil {
t.l.Err(err).Msg("could not get create workflow run opts")
return
}
workflowRun, err := t.repo.WorkflowRun().CreateNewWorkflowRun(tenantId, createOpts)
if err != nil {
t.l.Err(err).Msg("could not create workflow run")
return
}
for _, jobRun := range workflowRun.JobRuns() {
jobRunCp := jobRun
err = t.tq.AddTask(
context.Background(),
taskqueue.JOB_PROCESSING_QUEUE,
tasktypes.JobRunQueuedToTask(jobRun.Job(), &jobRunCp),
)
if err != nil {
t.l.Err(err).Msg("could not add job run queued task")
continue
}
}
// get the scheduler
schedulerVal, ok := t.scheduledWorkflows.Load(getScheduledWorkflowKey(workflowVersion.ID, scheduledWorkflowId))
if !ok {
// return fmt.Errorf("could not find scheduled workflow %s", payload.WorkflowVersionId)
t.l.Error().Msgf("could not find scheduled workflow %s", workflowVersion.ID)
return
}
defer t.scheduledWorkflows.Delete(workflowVersion.ID)
scheduler := schedulerVal.(gocron.Scheduler)
// cancel the schedule
err = scheduler.Shutdown()
if err != nil {
t.l.Err(err).Msg("could not cancel scheduler")
return
}
}
}
func (t *TickerImpl) handleCancelWorkflow(ctx context.Context, task *taskqueue.Task) error {
t.l.Debug().Msg("ticker: canceling scheduled workflow")
payload := tasktypes.CancelWorkflowTaskPayload{}
metadata := tasktypes.CancelWorkflowTaskMetadata{}
err := t.dv.DecodeAndValidate(task.Payload, &payload)
if err != nil {
return fmt.Errorf("could not decode ticker task payload: %w", err)
}
err = t.dv.DecodeAndValidate(task.Metadata, &metadata)
if err != nil {
return fmt.Errorf("could not decode ticker task metadata: %w", err)
}
// get the scheduler
schedulerVal, ok := t.scheduledWorkflows.Load(getScheduledWorkflowKey(payload.WorkflowVersionId, payload.ScheduledWorkflowId))
if !ok {
return fmt.Errorf("could not find scheduled workflow %s", payload.WorkflowVersionId)
}
defer t.scheduledWorkflows.Delete(getScheduledWorkflowKey(payload.WorkflowVersionId, payload.ScheduledWorkflowId))
schedulerP := schedulerVal.(*gocron.Scheduler)
scheduler := *schedulerP
// cancel the schedule
return scheduler.Shutdown()
}
func getScheduledWorkflowKey(workflowVersionId, scheduledWorkflowId string) string {
return fmt.Sprintf("%s-%s", workflowVersionId, scheduledWorkflowId)
}

View File

@@ -7,7 +7,7 @@ import (
"sync"
"time"
"github.com/go-co-op/gocron"
"github.com/go-co-op/gocron/v2"
"github.com/google/uuid"
"github.com/hatchet-dev/hatchet/internal/datautils"
"github.com/hatchet-dev/hatchet/internal/repository"
@@ -24,12 +24,13 @@ type TickerImpl struct {
tq taskqueue.TaskQueue
l *zerolog.Logger
repo repository.Repository
s *gocron.Scheduler
s gocron.Scheduler
crons sync.Map
jobRuns sync.Map
stepRuns sync.Map
stepRunRequeues sync.Map
crons sync.Map
scheduledWorkflows sync.Map
jobRuns sync.Map
stepRuns sync.Map
stepRunRequeues sync.Map
dv datautils.DataDecoderValidator
@@ -94,7 +95,11 @@ func New(fs ...TickerOpt) (*TickerImpl, error) {
return nil, fmt.Errorf("repository is required. use WithRepository")
}
s := gocron.NewScheduler(time.UTC)
s, err := gocron.NewScheduler(gocron.WithLocation(time.UTC))
if err != nil {
return nil, fmt.Errorf("could not create scheduler: %w", err)
}
return &TickerImpl{
tq: opts.tq,
@@ -125,19 +130,25 @@ func (t *TickerImpl) Start(ctx context.Context) error {
return err
}
_, err = t.s.Every(5).Seconds().Do(t.runStepRunRequeue(ctx))
_, err = t.s.NewJob(
gocron.DurationJob(time.Second*5),
gocron.NewTask(
t.runStepRunRequeue(ctx),
),
)
if err != nil {
return fmt.Errorf("could not schedule step run requeue: %w", err)
}
_, err = t.s.Every(5).Seconds().Do(t.runUpdateHeartbeat(ctx))
_, err = t.s.NewJob(
gocron.DurationJob(time.Second*5),
gocron.NewTask(
t.runUpdateHeartbeat(ctx),
),
)
if err != nil {
return fmt.Errorf("could not schedule heartbeat update: %w", err)
}
t.s.StartAsync()
t.s.Start()
for {
select {
@@ -194,6 +205,10 @@ func (t *TickerImpl) handleTask(ctx context.Context, task *taskqueue.Task) error
return t.handleScheduleCron(ctx, task)
case "cancel-cron":
return t.handleCancelCron(ctx, task)
case "schedule-workflow":
return t.handleScheduleWorkflow(ctx, task)
case "cancel-workflow":
return t.handleCancelWorkflow(ctx, task)
}
return fmt.Errorf("unknown task: %s in queue %s", task.ID, string(task.Queue))

View File

@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/Masterminds/semver/v3"
admincontracts "github.com/hatchet-dev/hatchet/internal/services/admin/contracts"
@@ -13,10 +14,12 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
)
type AdminClient interface {
PutWorkflow(workflow *types.Workflow, opts ...PutOptFunc) error
ScheduleWorkflow(workflowName string, schedules ...time.Time) error
}
type adminClientImpl struct {
@@ -120,6 +123,36 @@ func (a *adminClientImpl) PutWorkflow(workflow *types.Workflow, fs ...PutOptFunc
return nil
}
func (a *adminClientImpl) ScheduleWorkflow(workflowName string, schedules ...time.Time) error {
// get the workflow id from the name
workflow, err := a.client.GetWorkflowByName(context.Background(), &admincontracts.GetWorkflowByNameRequest{
TenantId: a.tenantId,
Name: workflowName,
})
if err != nil {
return fmt.Errorf("could not get workflow: %w", err)
}
pbSchedules := make([]*timestamppb.Timestamp, len(schedules))
for i, scheduled := range schedules {
pbSchedules[i] = timestamppb.New(scheduled)
}
_, err = a.client.ScheduleWorkflow(context.Background(), &admincontracts.ScheduleWorkflowRequest{
TenantId: a.tenantId,
WorkflowId: workflow.Id,
Schedules: pbSchedules,
})
if err != nil {
return fmt.Errorf("could not schedule workflow: %w", err)
}
return nil
}
func (a *adminClientImpl) getPutRequest(workflow *types.Workflow) (*admincontracts.PutWorkflowRequest, error) {
opts := &admincontracts.CreateWorkflowVersionOpts{
Name: workflow.Name,
@@ -162,6 +195,12 @@ func (a *adminClientImpl) getPutRequest(workflow *types.Workflow) (*admincontrac
jobOpts = append(jobOpts, jobOpt)
}
opts.ScheduledTriggers = make([]*timestamppb.Timestamp, len(workflow.Triggers.Schedules))
for i, scheduled := range workflow.Triggers.Schedules {
opts.ScheduledTriggers[i] = timestamppb.New(scheduled)
}
opts.Jobs = jobOpts
return &admincontracts.PutWorkflowRequest{

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"fmt"
"time"
"gopkg.in/yaml.v3"
)
@@ -21,8 +22,9 @@ type Workflow struct {
}
type WorkflowTriggers struct {
Events []string `yaml:"events,omitempty"`
Cron []string `yaml:"crons,omitempty"`
Events []string `yaml:"events,omitempty"`
Cron []string `yaml:"crons,omitempty"`
Schedules []time.Time `yaml:"schedules,omitempty"`
}
type RandomScheduleOpt string

View File

@@ -2,7 +2,6 @@ package worker
import (
"fmt"
"reflect"
"github.com/hatchet-dev/hatchet/pkg/client"
"github.com/hatchet-dev/hatchet/pkg/client/types"
@@ -49,17 +48,7 @@ func (s *Service) On(t triggerConverter, workflow workflowConverter) error {
}
func (s *Service) RegisterAction(fn any) error {
fnType := reflect.TypeOf(fn)
if fnType.Kind() != reflect.Func {
return fmt.Errorf("method must be a function")
}
if fnType.Name() == "" {
return fmt.Errorf("function cannot be anonymous")
}
fnId := fnType.Name()
fnId := getFnName(fn)
actionId := fmt.Sprintf("%s:%s", s.Name, fnId)

View File

@@ -5,6 +5,7 @@ import (
"reflect"
"runtime"
"strings"
"time"
"github.com/hatchet-dev/hatchet/pkg/client/types"
)
@@ -41,6 +42,20 @@ func (c cronArr) ToWorkflowTriggers(wt *types.WorkflowTriggers) {
wt.Cron = append(wt.Cron, c...)
}
type scheduled []time.Time
func At(t ...time.Time) scheduled {
return scheduled(t)
}
func (s scheduled) ToWorkflowTriggers(wt *types.WorkflowTriggers) {
if wt.Schedules == nil {
wt.Schedules = []time.Time{}
}
wt.Schedules = append(wt.Schedules, s...)
}
type event string
func Event(e string) event {

View File

@@ -145,6 +145,16 @@ CREATE TABLE "WorkflowTriggerCronRef" (
"tickerId" UUID
);
-- CreateTable
CREATE TABLE "WorkflowTriggerScheduledRef" (
"id" UUID NOT NULL,
"parentId" UUID NOT NULL,
"triggerAt" TIMESTAMP(3) NOT NULL,
"tickerId" UUID,
CONSTRAINT "WorkflowTriggerScheduledRef_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Job" (
"id" UUID NOT NULL,
@@ -214,6 +224,7 @@ CREATE TABLE "WorkflowRunTriggeredBy" (
"eventId" UUID,
"cronParentId" UUID,
"cronSchedule" TEXT,
"scheduledId" UUID,
CONSTRAINT "WorkflowRunTriggeredBy_pkey" PRIMARY KEY ("id")
);
@@ -406,6 +417,9 @@ CREATE UNIQUE INDEX "WorkflowTriggerEventRef_parentId_eventKey_key" ON "Workflow
-- CreateIndex
CREATE UNIQUE INDEX "WorkflowTriggerCronRef_parentId_cron_key" ON "WorkflowTriggerCronRef"("parentId", "cron");
-- CreateIndex
CREATE UNIQUE INDEX "WorkflowTriggerScheduledRef_id_key" ON "WorkflowTriggerScheduledRef"("id");
-- CreateIndex
CREATE UNIQUE INDEX "Job_id_key" ON "Job"("id");
@@ -433,6 +447,9 @@ CREATE UNIQUE INDEX "WorkflowRunTriggeredBy_id_key" ON "WorkflowRunTriggeredBy"(
-- CreateIndex
CREATE UNIQUE INDEX "WorkflowRunTriggeredBy_parentId_key" ON "WorkflowRunTriggeredBy"("parentId");
-- CreateIndex
CREATE UNIQUE INDEX "WorkflowRunTriggeredBy_scheduledId_key" ON "WorkflowRunTriggeredBy"("scheduledId");
-- CreateIndex
CREATE UNIQUE INDEX "WorkflowRunTriggeredBy_tenantId_parentId_key" ON "WorkflowRunTriggeredBy"("tenantId", "parentId");
@@ -529,6 +546,12 @@ ALTER TABLE "WorkflowTriggerCronRef" ADD CONSTRAINT "WorkflowTriggerCronRef_pare
-- AddForeignKey
ALTER TABLE "WorkflowTriggerCronRef" ADD CONSTRAINT "WorkflowTriggerCronRef_tickerId_fkey" FOREIGN KEY ("tickerId") REFERENCES "Ticker"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "WorkflowTriggerScheduledRef" ADD CONSTRAINT "WorkflowTriggerScheduledRef_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "WorkflowVersion"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "WorkflowTriggerScheduledRef" ADD CONSTRAINT "WorkflowTriggerScheduledRef_tickerId_fkey" FOREIGN KEY ("tickerId") REFERENCES "Ticker"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Job" ADD CONSTRAINT "Job_tenantId_fkey" FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -568,6 +591,9 @@ ALTER TABLE "WorkflowRunTriggeredBy" ADD CONSTRAINT "WorkflowRunTriggeredBy_even
-- AddForeignKey
ALTER TABLE "WorkflowRunTriggeredBy" ADD CONSTRAINT "WorkflowRunTriggeredBy_cronParentId_cronSchedule_fkey" FOREIGN KEY ("cronParentId", "cronSchedule") REFERENCES "WorkflowTriggerCronRef"("parentId", "cron") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "WorkflowRunTriggeredBy" ADD CONSTRAINT "WorkflowRunTriggeredBy_scheduledId_fkey" FOREIGN KEY ("scheduledId") REFERENCES "WorkflowTriggerScheduledRef"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "JobRun" ADD CONSTRAINT "JobRun_tenantId_fkey" FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -215,6 +215,9 @@ model WorkflowVersion {
// all runs for the workflow
runs WorkflowRun[]
// the scheduled runs for the workflow
scheduled WorkflowTriggerScheduledRef[]
// versions are unique per workflow
@@unique([workflowId, version])
}
@@ -270,6 +273,23 @@ model WorkflowTriggerCronRef {
@@unique([parentId, cron])
}
model WorkflowTriggerScheduledRef {
id String @id @unique @default(uuid()) @db.Uuid
// the parent workflow
parent WorkflowVersion @relation(fields: [parentId], references: [id], onDelete: Cascade, onUpdate: Cascade)
parentId String @db.Uuid
// the time that the workflow should be triggered
triggerAt DateTime
// the assigned ticker
ticker Ticker? @relation(fields: [tickerId], references: [id])
tickerId String? @db.Uuid
triggered WorkflowRunTriggeredBy?
}
model Job {
// base fields
id String @id @unique @default(uuid()) @db.Uuid
@@ -431,6 +451,10 @@ model WorkflowRunTriggeredBy {
cronParentId String? @db.Uuid
cronSchedule String?
// a specific time that triggered this workflow
scheduled WorkflowTriggerScheduledRef? @relation(fields: [scheduledId], references: [id])
scheduledId String? @unique @db.Uuid
@@unique([tenantId, parentId])
}
@@ -625,9 +649,10 @@ model Ticker {
// the last heartbeat time
lastHeartbeatAt DateTime?
jobRuns JobRun[]
stepRuns StepRun[]
crons WorkflowTriggerCronRef[]
jobRuns JobRun[]
stepRuns StepRun[]
crons WorkflowTriggerCronRef[]
scheduled WorkflowTriggerScheduledRef[]
}
enum WorkerStatus {