mirror of
https://github.com/hatchet-dev/hatchet.git
synced 2026-05-06 18:09:49 -05:00
feat: expression-based concurrency keys (#889)
* feat: expression-based concurrency keys * fix: build * fix: typos * fix: gen * fix: migration * fix: remove print statements * fix: reassignment bugs, retries on closed transport, pr review
This commit is contained in:
@@ -14,3 +14,4 @@ extend-ignore-re = [
|
||||
|
||||
[default.extend-words]
|
||||
datas = "datas"
|
||||
strat = "strat"
|
||||
|
||||
@@ -395,6 +395,8 @@ StepRunEventReason:
|
||||
- TIMED_OUT
|
||||
- SLOT_RELEASED
|
||||
- RETRIED_BY_USER
|
||||
- WORKFLOW_RUN_GROUP_KEY_SUCCEEDED
|
||||
- WORKFLOW_RUN_GROUP_KEY_FAILED
|
||||
|
||||
StepRunEventSeverity:
|
||||
type: string
|
||||
@@ -416,6 +418,8 @@ StepRunEvent:
|
||||
format: date-time
|
||||
stepRunId:
|
||||
type: string
|
||||
workflowRunId:
|
||||
type: string
|
||||
reason:
|
||||
$ref: "#/StepRunEventReason"
|
||||
severity:
|
||||
@@ -430,7 +434,6 @@ StepRunEvent:
|
||||
- id
|
||||
- timeFirstSeen
|
||||
- timeLastSeen
|
||||
- stepRunId
|
||||
- reason
|
||||
- severity
|
||||
- message
|
||||
|
||||
@@ -53,9 +53,10 @@ enum ConcurrencyLimitStrategy {
|
||||
}
|
||||
|
||||
message WorkflowConcurrencyOpts {
|
||||
string action = 1; // (required) the action id for getting the concurrency group
|
||||
int32 max_runs = 2; // (optional) the maximum number of concurrent workflow runs, default 1
|
||||
ConcurrencyLimitStrategy limit_strategy = 3; // (optional) the strategy to use when the concurrency limit is reached, default CANCEL_IN_PROGRESS
|
||||
optional string action = 1; // (optional) the action id for getting the concurrency group
|
||||
optional int32 max_runs = 2; // (optional) the maximum number of concurrent workflow runs, default 1
|
||||
optional ConcurrencyLimitStrategy limit_strategy = 3; // (optional) the strategy to use when the concurrency limit is reached, default CANCEL_IN_PROGRESS
|
||||
optional string expression = 4; // (optional) the expression to use for concurrency
|
||||
}
|
||||
|
||||
// CreateWorkflowJobOpts represents options to create a workflow job.
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
func (t *WorkflowRunsService) WorkflowRunGetInput(ctx echo.Context, request gen.WorkflowRunGetInputRequestObject) (gen.WorkflowRunGetInputResponseObject, error) {
|
||||
|
||||
input, err := t.config.APIRepository.WorkflowRun().GetWorkflowRunInputData(request.Tenant.String(), request.WorkflowRun.String())
|
||||
input, err := t.config.EngineRepository.WorkflowRun().GetWorkflowRunInputData(request.Tenant.String(), request.WorkflowRun.String())
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -67,20 +67,22 @@ const (
|
||||
|
||||
// Defines values for StepRunEventReason.
|
||||
const (
|
||||
StepRunEventReasonASSIGNED StepRunEventReason = "ASSIGNED"
|
||||
StepRunEventReasonCANCELLED StepRunEventReason = "CANCELLED"
|
||||
StepRunEventReasonFAILED StepRunEventReason = "FAILED"
|
||||
StepRunEventReasonFINISHED StepRunEventReason = "FINISHED"
|
||||
StepRunEventReasonREASSIGNED StepRunEventReason = "REASSIGNED"
|
||||
StepRunEventReasonREQUEUEDNOWORKER StepRunEventReason = "REQUEUED_NO_WORKER"
|
||||
StepRunEventReasonREQUEUEDRATELIMIT StepRunEventReason = "REQUEUED_RATE_LIMIT"
|
||||
StepRunEventReasonRETRIEDBYUSER StepRunEventReason = "RETRIED_BY_USER"
|
||||
StepRunEventReasonRETRYING StepRunEventReason = "RETRYING"
|
||||
StepRunEventReasonSCHEDULINGTIMEDOUT StepRunEventReason = "SCHEDULING_TIMED_OUT"
|
||||
StepRunEventReasonSLOTRELEASED StepRunEventReason = "SLOT_RELEASED"
|
||||
StepRunEventReasonSTARTED StepRunEventReason = "STARTED"
|
||||
StepRunEventReasonTIMEDOUT StepRunEventReason = "TIMED_OUT"
|
||||
StepRunEventReasonTIMEOUTREFRESHED StepRunEventReason = "TIMEOUT_REFRESHED"
|
||||
StepRunEventReasonASSIGNED StepRunEventReason = "ASSIGNED"
|
||||
StepRunEventReasonCANCELLED StepRunEventReason = "CANCELLED"
|
||||
StepRunEventReasonFAILED StepRunEventReason = "FAILED"
|
||||
StepRunEventReasonFINISHED StepRunEventReason = "FINISHED"
|
||||
StepRunEventReasonREASSIGNED StepRunEventReason = "REASSIGNED"
|
||||
StepRunEventReasonREQUEUEDNOWORKER StepRunEventReason = "REQUEUED_NO_WORKER"
|
||||
StepRunEventReasonREQUEUEDRATELIMIT StepRunEventReason = "REQUEUED_RATE_LIMIT"
|
||||
StepRunEventReasonRETRIEDBYUSER StepRunEventReason = "RETRIED_BY_USER"
|
||||
StepRunEventReasonRETRYING StepRunEventReason = "RETRYING"
|
||||
StepRunEventReasonSCHEDULINGTIMEDOUT StepRunEventReason = "SCHEDULING_TIMED_OUT"
|
||||
StepRunEventReasonSLOTRELEASED StepRunEventReason = "SLOT_RELEASED"
|
||||
StepRunEventReasonSTARTED StepRunEventReason = "STARTED"
|
||||
StepRunEventReasonTIMEDOUT StepRunEventReason = "TIMED_OUT"
|
||||
StepRunEventReasonTIMEOUTREFRESHED StepRunEventReason = "TIMEOUT_REFRESHED"
|
||||
StepRunEventReasonWORKFLOWRUNGROUPKEYFAILED StepRunEventReason = "WORKFLOW_RUN_GROUP_KEY_FAILED"
|
||||
StepRunEventReasonWORKFLOWRUNGROUPKEYSUCCEEDED StepRunEventReason = "WORKFLOW_RUN_GROUP_KEY_SUCCEEDED"
|
||||
)
|
||||
|
||||
// Defines values for StepRunEventSeverity.
|
||||
@@ -669,9 +671,10 @@ type StepRunEvent struct {
|
||||
Message string `json:"message"`
|
||||
Reason StepRunEventReason `json:"reason"`
|
||||
Severity StepRunEventSeverity `json:"severity"`
|
||||
StepRunId string `json:"stepRunId"`
|
||||
StepRunId *string `json:"stepRunId,omitempty"`
|
||||
TimeFirstSeen time.Time `json:"timeFirstSeen"`
|
||||
TimeLastSeen time.Time `json:"timeLastSeen"`
|
||||
WorkflowRunId *string `json:"workflowRunId,omitempty"`
|
||||
}
|
||||
|
||||
// StepRunEventList defines model for StepRunEventList.
|
||||
@@ -8886,176 +8889,177 @@ func (sh *strictHandler) WorkflowVersionGet(ctx echo.Context, workflow openapi_t
|
||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||
var swaggerSpec = []string{
|
||||
|
||||
"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",
|
||||
"/w8AAP//Zv+ztY2oAQA=",
|
||||
}
|
||||
|
||||
// GetSwagger returns the content of the embedded swagger specification file
|
||||
|
||||
@@ -310,13 +310,22 @@ func ToStepRunEvent(stepRunEvent *dbsqlc.StepRunEvent) *gen.StepRunEvent {
|
||||
Id: int(stepRunEvent.ID),
|
||||
TimeFirstSeen: stepRunEvent.TimeFirstSeen.Time,
|
||||
TimeLastSeen: stepRunEvent.TimeLastSeen.Time,
|
||||
StepRunId: sqlchelpers.UUIDToStr(stepRunEvent.StepRunId),
|
||||
Severity: gen.StepRunEventSeverity(stepRunEvent.Severity),
|
||||
Reason: gen.StepRunEventReason(stepRunEvent.Reason),
|
||||
Message: stepRunEvent.Message,
|
||||
Count: int(stepRunEvent.Count),
|
||||
}
|
||||
|
||||
if stepRunEvent.StepRunId.Valid {
|
||||
srId := sqlchelpers.UUIDToStr(stepRunEvent.StepRunId)
|
||||
res.StepRunId = &srId
|
||||
}
|
||||
|
||||
if stepRunEvent.WorkflowRunId.Valid {
|
||||
wrId := sqlchelpers.UUIDToStr(stepRunEvent.WorkflowRunId)
|
||||
res.WorkflowRunId = &wrId
|
||||
}
|
||||
|
||||
if stepRunEvent.Data != nil {
|
||||
data := make(map[string]interface{})
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ func seedDev(repo repository.EngineRepository, tenantId string) error {
|
||||
},
|
||||
},
|
||||
Concurrency: &repository.CreateWorkflowConcurrencyOpts{
|
||||
Action: "test:concurrency",
|
||||
Action: repository.StringPtr("test:concurrency"),
|
||||
},
|
||||
Jobs: []repository.CreateWorkflowJobOpts{
|
||||
{
|
||||
|
||||
@@ -70,7 +70,7 @@ func run(events chan<- string) (func() error, error) {
|
||||
On: worker.Events("user:create:simple"),
|
||||
Name: "simple",
|
||||
Description: "This runs after an update to the user model.",
|
||||
Concurrency: worker.Concurrency(getConcurrencyKey),
|
||||
Concurrency: worker.Expression("input.user_id"),
|
||||
Steps: []*worker.WorkflowStep{
|
||||
worker.Fn(func(ctx worker.HatchetContext) (result *stepOneOutput, err error) {
|
||||
input := &userCreateEvent{}
|
||||
|
||||
@@ -843,6 +843,8 @@ export enum StepRunEventReason {
|
||||
TIMED_OUT = 'TIMED_OUT',
|
||||
SLOT_RELEASED = 'SLOT_RELEASED',
|
||||
RETRIED_BY_USER = 'RETRIED_BY_USER',
|
||||
WORKFLOW_RUN_GROUP_KEY_SUCCEEDED = 'WORKFLOW_RUN_GROUP_KEY_SUCCEEDED',
|
||||
WORKFLOW_RUN_GROUP_KEY_FAILED = 'WORKFLOW_RUN_GROUP_KEY_FAILED',
|
||||
}
|
||||
|
||||
export enum StepRunEventSeverity {
|
||||
@@ -857,7 +859,8 @@ export interface StepRunEvent {
|
||||
timeFirstSeen: string;
|
||||
/** @format date-time */
|
||||
timeLastSeen: string;
|
||||
stepRunId: string;
|
||||
stepRunId?: string;
|
||||
workflowRunId?: string;
|
||||
reason: StepRunEventReason;
|
||||
severity: StepRunEventSeverity;
|
||||
message: string;
|
||||
|
||||
@@ -205,6 +205,9 @@ const REASON_TO_TITLE: Record<StepRunEventReason, string> = {
|
||||
[StepRunEventReason.TIMED_OUT]: 'Execution timed out',
|
||||
[StepRunEventReason.SLOT_RELEASED]: 'Slot released',
|
||||
[StepRunEventReason.RETRIED_BY_USER]: 'Replayed by user',
|
||||
[StepRunEventReason.WORKFLOW_RUN_GROUP_KEY_SUCCEEDED]:
|
||||
'Successfully got group key',
|
||||
[StepRunEventReason.WORKFLOW_RUN_GROUP_KEY_FAILED]: 'Failed to get group key',
|
||||
};
|
||||
|
||||
function getTitleFromReason(reason: StepRunEventReason, message: string) {
|
||||
|
||||
@@ -52,20 +52,25 @@ export const columns = ({
|
||||
header: ({ column }) => (
|
||||
<DataTableColumnHeader column={column} title="Task" />
|
||||
),
|
||||
cell: ({ row }) => (
|
||||
<div className="min-w-[120px] max-w-[180px]">
|
||||
<Badge
|
||||
className="cursor-pointer text-xs font-mono py-1 bg-[#ffffff] dark:bg-[#050c1c] border-[#050c1c] dark:border-gray-400"
|
||||
variant="outline"
|
||||
onClick={() => onRowClick(row.original)}
|
||||
>
|
||||
<ArrowLeftEndOnRectangleIcon className="w-4 h-4 mr-1" />
|
||||
<div className="truncate max-w-[150px]">
|
||||
{row.original.step?.readableId}
|
||||
</div>
|
||||
</Badge>
|
||||
</div>
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
if (!row.original.stepRun) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div className="min-w-[120px] max-w-[180px]">
|
||||
<Badge
|
||||
className="cursor-pointer text-xs font-mono py-1 bg-[#ffffff] dark:bg-[#050c1c] border-[#050c1c] dark:border-gray-400"
|
||||
variant="outline"
|
||||
onClick={() => onRowClick(row.original)}
|
||||
>
|
||||
<ArrowLeftEndOnRectangleIcon className="w-4 h-4 mr-1" />
|
||||
<div className="truncate max-w-[150px]">
|
||||
{row.original.step?.readableId}
|
||||
</div>
|
||||
</Badge>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
});
|
||||
@@ -171,6 +176,9 @@ const REASON_TO_TITLE: Record<StepRunEventReason, string> = {
|
||||
[StepRunEventReason.TIMED_OUT]: 'Execution timed out',
|
||||
[StepRunEventReason.SLOT_RELEASED]: 'Slot released',
|
||||
[StepRunEventReason.RETRIED_BY_USER]: 'Replayed by user',
|
||||
[StepRunEventReason.WORKFLOW_RUN_GROUP_KEY_SUCCEEDED]:
|
||||
'Successfully got group key',
|
||||
[StepRunEventReason.WORKFLOW_RUN_GROUP_KEY_FAILED]: 'Failed to get group key',
|
||||
};
|
||||
|
||||
function getTitleFromReason(reason: StepRunEventReason, message: string) {
|
||||
|
||||
+6
-2
@@ -100,8 +100,12 @@ export function StepRunEvents({
|
||||
updatedAt: item.timeLastSeen,
|
||||
},
|
||||
event: item,
|
||||
stepRun: normalizedStepRunsByStepRunId[item.stepRunId],
|
||||
step: normalizedStepsByStepRunId[item.stepRunId],
|
||||
stepRun: item.stepRunId
|
||||
? normalizedStepRunsByStepRunId[item.stepRunId]
|
||||
: undefined,
|
||||
step: item.stepRunId
|
||||
? normalizedStepsByStepRunId[item.stepRunId]
|
||||
: undefined,
|
||||
};
|
||||
}) || [];
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ require (
|
||||
cloud.google.com/go/auth v0.9.3 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.0 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
@@ -96,6 +97,7 @@ require (
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
@@ -127,6 +129,7 @@ require (
|
||||
github.com/go-playground/validator/v10 v10.22.1
|
||||
github.com/go-test/deep v1.1.0 // indirect
|
||||
github.com/goccy/go-json v0.10.3
|
||||
github.com/google/cel-go v0.21.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/schema v1.4.1
|
||||
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0
|
||||
|
||||
@@ -9,6 +9,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
|
||||
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
||||
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
||||
@@ -109,6 +111,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/cel-go v0.21.0 h1:cl6uW/gxN+Hy50tNYvI691+sXxioCnstFzLp2WO4GCI=
|
||||
github.com/google/cel-go v0.21.0/go.mod h1:rHUlWCcBKgyEk+eV03RPdZUekPp6YcJwV0FxuUksYxc=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
@@ -282,6 +286,8 @@ github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+
|
||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
|
||||
github.com/steebchen/prisma-client-go v0.41.0 h1:j5ORS7kweZLkvJByy8xBkSSltjQVCkES3VuuWPgfPNk=
|
||||
github.com/steebchen/prisma-client-go v0.41.0/go.mod h1:wp2xU9HO5WIefc65vcl1HOiFUzaHKyOhHw5atrzs8hc=
|
||||
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
|
||||
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package cel
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/checker/decls"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
expr "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
||||
)
|
||||
|
||||
type CELParser struct {
|
||||
workflowStrEnv *cel.Env
|
||||
}
|
||||
|
||||
var checksumDecl = decls.NewFunction("checksum",
|
||||
decls.NewOverload("checksum_string",
|
||||
[]*expr.Type{decls.String},
|
||||
decls.String,
|
||||
),
|
||||
)
|
||||
|
||||
var checksum = cel.Function("checksum",
|
||||
cel.MemberOverload(
|
||||
"checksum_string_impl",
|
||||
[]*cel.Type{cel.StringType},
|
||||
cel.StringType,
|
||||
cel.FunctionBinding(func(args ...ref.Val) ref.Val {
|
||||
if len(args) != 1 {
|
||||
return types.NewErr("checksum requires 1 argument")
|
||||
}
|
||||
str, ok := args[0].(types.String)
|
||||
if !ok {
|
||||
return types.NewErr("argument must be a string")
|
||||
}
|
||||
hash := sha256.Sum256([]byte(str))
|
||||
return types.String(fmt.Sprintf("%x", hash))
|
||||
})),
|
||||
)
|
||||
|
||||
func NewCELParser() *CELParser {
|
||||
workflowStrEnv, _ := cel.NewEnv(
|
||||
cel.Declarations(
|
||||
decls.NewVar("input", decls.NewMapType(decls.String, decls.Dyn)),
|
||||
decls.NewVar("additional_metadata", decls.NewMapType(decls.String, decls.Dyn)),
|
||||
decls.NewVar("workflow_run_id", decls.String),
|
||||
checksumDecl,
|
||||
),
|
||||
checksum,
|
||||
)
|
||||
|
||||
return &CELParser{
|
||||
workflowStrEnv: workflowStrEnv,
|
||||
}
|
||||
}
|
||||
|
||||
type WorkflowStringInput map[string]interface{}
|
||||
|
||||
type WorkflowStringInputOpts func(WorkflowStringInput)
|
||||
|
||||
func WithInput(input map[string]interface{}) WorkflowStringInputOpts {
|
||||
return func(w WorkflowStringInput) {
|
||||
w["input"] = input
|
||||
}
|
||||
}
|
||||
|
||||
func WithAdditionalMetadata(metadata map[string]interface{}) WorkflowStringInputOpts {
|
||||
return func(w WorkflowStringInput) {
|
||||
w["additional_metadata"] = metadata
|
||||
}
|
||||
}
|
||||
|
||||
func WithWorkflowRunID(workflowRunID string) WorkflowStringInputOpts {
|
||||
return func(w WorkflowStringInput) {
|
||||
w["workflow_run_id"] = workflowRunID
|
||||
}
|
||||
}
|
||||
|
||||
func NewWorkflowStringInput(opts ...WorkflowStringInputOpts) WorkflowStringInput {
|
||||
res := make(map[string]interface{})
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(res)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (p *CELParser) ParseWorkflowString(workflowExp string) (cel.Program, error) {
|
||||
ast, issues := p.workflowStrEnv.Compile(workflowExp)
|
||||
|
||||
if issues != nil && issues.Err() != nil {
|
||||
return nil, issues.Err()
|
||||
}
|
||||
|
||||
return p.workflowStrEnv.Program(ast)
|
||||
}
|
||||
|
||||
func (p *CELParser) ParseAndEvalWorkflowString(workflowExp string, in WorkflowStringInput) (string, error) {
|
||||
prg, err := p.ParseWorkflowString(workflowExp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var inMap map[string]interface{} = in
|
||||
|
||||
out, _, err := prg.Eval(inMap)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return out.Value().(string), nil
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package cel_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/cel-go/common/types"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/internal/cel"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCELParser(t *testing.T) {
|
||||
parser := cel.NewCELParser()
|
||||
|
||||
tests := []struct {
|
||||
expression string
|
||||
input cel.WorkflowStringInput
|
||||
expected string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
expression: `has(input.custom.value) ? input.custom.value : "default"`,
|
||||
input: cel.NewWorkflowStringInput(
|
||||
cel.WithInput(map[string]interface{}{
|
||||
"custom": map[string]interface{}{
|
||||
"value": "actual value",
|
||||
},
|
||||
}),
|
||||
),
|
||||
expected: "actual value",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
expression: `has(input.custom) ? input.custom.value : "default"`,
|
||||
input: cel.NewWorkflowStringInput(
|
||||
cel.WithInput(map[string]interface{}{}),
|
||||
),
|
||||
expected: "default",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
expression: `checksum(input.custom.value)`,
|
||||
input: cel.NewWorkflowStringInput(
|
||||
cel.WithInput(map[string]interface{}{
|
||||
"custom": map[string]interface{}{
|
||||
"value": "checksum this",
|
||||
},
|
||||
}),
|
||||
),
|
||||
expected: types.String("97e9269cd0514f864e6be9157998464c94776ebc7f669b449f581abdad4035f5").Value().(string), // Precomputed checksum
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
expression: `input.custom.value + workflow_run_id`,
|
||||
input: cel.NewWorkflowStringInput(
|
||||
cel.WithInput(map[string]interface{}{
|
||||
"custom": map[string]interface{}{
|
||||
"value": "concatenate ",
|
||||
},
|
||||
}),
|
||||
cel.WithWorkflowRunID("1234"),
|
||||
),
|
||||
expected: "concatenate 1234",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
expression: `checksum(input.missing_key)`, // Should throw an error due to missing key
|
||||
input: cel.NewWorkflowStringInput(),
|
||||
expected: "",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
expression: `input.custom.value + 1234`, // Invalid expression (mismatched types), expecting error
|
||||
input: cel.NewWorkflowStringInput(),
|
||||
expected: "",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.expression, func(t *testing.T) {
|
||||
result, err := parser.ParseAndEvalWorkflowString(tt.expression, tt.input)
|
||||
|
||||
if tt.expectError {
|
||||
assert.Error(t, err, "Expected error but got none")
|
||||
} else {
|
||||
assert.NoError(t, err, "Did not expect error but got one")
|
||||
assert.Equal(t, tt.expected, result, "Unexpected result")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package queueutils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type OpMethod func(ctx context.Context, id string) (bool, error)
|
||||
|
||||
// SerialOperation represents a method that can only run serially.
|
||||
type SerialOperation struct {
|
||||
mu sync.RWMutex
|
||||
shouldContinue bool
|
||||
isRunning bool
|
||||
id string
|
||||
lastRun time.Time
|
||||
description string
|
||||
timeout time.Duration
|
||||
method OpMethod
|
||||
}
|
||||
|
||||
func (o *SerialOperation) RunOrContinue(ql *zerolog.Logger) {
|
||||
|
||||
o.setContinue(true)
|
||||
o.Run(ql)
|
||||
}
|
||||
|
||||
func (o *SerialOperation) Run(ql *zerolog.Logger) {
|
||||
if !o.setRunning(true, ql) {
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
o.setRunning(false, ql)
|
||||
}()
|
||||
|
||||
f := func() {
|
||||
o.setContinue(false)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), o.timeout)
|
||||
defer cancel()
|
||||
|
||||
shouldContinue, err := o.method(ctx, o.id)
|
||||
|
||||
if err != nil {
|
||||
ql.Err(err).Msgf("could not %s", o.description)
|
||||
return
|
||||
}
|
||||
|
||||
// if a continue was set during execution of the scheduler, we'd like to continue no matter what.
|
||||
// if a continue was not set, we'd like to set it to the value returned by the scheduler.
|
||||
if !o.getContinue() {
|
||||
o.setContinue(shouldContinue)
|
||||
}
|
||||
}
|
||||
|
||||
f()
|
||||
|
||||
for o.getContinue() {
|
||||
f()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// setRunning sets the running state of the operation and returns true if the state was changed,
|
||||
// false if the state was not changed.
|
||||
func (o *SerialOperation) setRunning(isRunning bool, ql *zerolog.Logger) bool {
|
||||
o.mu.Lock()
|
||||
defer o.mu.Unlock()
|
||||
|
||||
if isRunning == o.isRunning {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if isRunning {
|
||||
|
||||
ql.Info().Str("tenant_id", o.id).TimeDiff("last_run", time.Now(), o.lastRun).Msg(o.description)
|
||||
|
||||
o.lastRun = time.Now()
|
||||
|
||||
}
|
||||
|
||||
o.isRunning = isRunning
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *SerialOperation) setContinue(shouldContinue bool) {
|
||||
o.mu.Lock()
|
||||
defer o.mu.Unlock()
|
||||
|
||||
o.shouldContinue = shouldContinue
|
||||
}
|
||||
|
||||
func (o *SerialOperation) getContinue() bool {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
return o.shouldContinue
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package queueutils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var l = zerolog.Nop()
|
||||
|
||||
func TestSerialOperation_RunOrContinue_NoConcurrentExecution(t *testing.T) {
|
||||
var runCount int
|
||||
var mu sync.Mutex
|
||||
|
||||
mockMethod := func(ctx context.Context, id string) (bool, error) {
|
||||
if !mu.TryLock() {
|
||||
panic("Concurrent execution detected")
|
||||
}
|
||||
|
||||
runCount++
|
||||
mu.Unlock()
|
||||
|
||||
time.Sleep(100 * time.Millisecond) // Simulate method execution time
|
||||
return false, nil
|
||||
}
|
||||
|
||||
operation := &SerialOperation{
|
||||
id: "1234",
|
||||
description: "Test operation",
|
||||
timeout: 2 * time.Second,
|
||||
method: mockMethod,
|
||||
}
|
||||
|
||||
// First run
|
||||
operation.RunOrContinue(&l)
|
||||
|
||||
// Try to trigger a set of runs concurrently, it should not start until the first finishes
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
operation.RunOrContinue(&l)
|
||||
operation.RunOrContinue(&l)
|
||||
operation.RunOrContinue(&l)
|
||||
operation.RunOrContinue(&l)
|
||||
|
||||
// Wait for both to finish
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
|
||||
mu.Lock()
|
||||
assert.Equal(t, 2, runCount, "The method should not run concurrently")
|
||||
mu.Unlock()
|
||||
}
|
||||
|
||||
func TestSerialOperation_RunOrContinue_ShouldRunAfterCompletion(t *testing.T) {
|
||||
var runCount int
|
||||
var mu sync.Mutex
|
||||
|
||||
mockMethod := func(ctx context.Context, id string) (bool, error) {
|
||||
mu.Lock()
|
||||
runCount++
|
||||
mu.Unlock()
|
||||
|
||||
time.Sleep(50 * time.Millisecond) // Simulate method execution time
|
||||
return false, nil
|
||||
}
|
||||
|
||||
operation := &SerialOperation{
|
||||
id: "1234",
|
||||
description: "Test operation",
|
||||
timeout: 2 * time.Second,
|
||||
method: mockMethod,
|
||||
}
|
||||
|
||||
// First run
|
||||
operation.RunOrContinue(&l)
|
||||
time.Sleep(110 * time.Millisecond)
|
||||
|
||||
// Second run after first finishes
|
||||
operation.RunOrContinue(&l)
|
||||
time.Sleep(110 * time.Millisecond)
|
||||
|
||||
mu.Lock()
|
||||
assert.Equal(t, 2, runCount, "The method should run twice after completion")
|
||||
mu.Unlock()
|
||||
}
|
||||
|
||||
func TestSerialOperation_RunOrContinue_ShouldRunOnContinues(t *testing.T) {
|
||||
var runCount int
|
||||
var mu sync.Mutex
|
||||
|
||||
mockMethod := func(ctx context.Context, id string) (bool, error) {
|
||||
mu.Lock()
|
||||
runCount++
|
||||
mu.Unlock()
|
||||
|
||||
time.Sleep(25 * time.Millisecond) // Simulate method execution time
|
||||
return runCount < 5, nil
|
||||
}
|
||||
|
||||
operation := &SerialOperation{
|
||||
id: "1234",
|
||||
description: "Test operation",
|
||||
timeout: 2 * time.Second,
|
||||
method: mockMethod,
|
||||
}
|
||||
|
||||
// First run
|
||||
operation.RunOrContinue(&l)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
|
||||
mu.Lock()
|
||||
assert.Equal(t, 5, runCount, "The method should run five times on continue")
|
||||
mu.Unlock()
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package queueutils
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type OperationPool struct {
|
||||
ops sync.Map
|
||||
timeout time.Duration
|
||||
description string
|
||||
method OpMethod
|
||||
ql *zerolog.Logger
|
||||
}
|
||||
|
||||
func NewOperationPool(ql *zerolog.Logger, timeout time.Duration, description string, method OpMethod) *OperationPool {
|
||||
return &OperationPool{
|
||||
timeout: timeout,
|
||||
description: description,
|
||||
method: method,
|
||||
ql: ql,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *OperationPool) RunOrContinue(id string) {
|
||||
p.GetOperation(id).RunOrContinue(p.ql)
|
||||
}
|
||||
|
||||
func (p *OperationPool) GetOperation(id string) *SerialOperation {
|
||||
op, ok := p.ops.Load(id)
|
||||
|
||||
if !ok {
|
||||
op = &SerialOperation{
|
||||
id: id,
|
||||
lastRun: time.Now(),
|
||||
description: p.description,
|
||||
timeout: p.timeout,
|
||||
method: p.method,
|
||||
}
|
||||
|
||||
p.ops.Store(id, op)
|
||||
}
|
||||
|
||||
return op.(*SerialOperation)
|
||||
}
|
||||
@@ -491,9 +491,10 @@ type WorkflowConcurrencyOpts struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Action string `protobuf:"bytes,1,opt,name=action,proto3" json:"action,omitempty"` // (required) the action id for getting the concurrency group
|
||||
MaxRuns int32 `protobuf:"varint,2,opt,name=max_runs,json=maxRuns,proto3" json:"max_runs,omitempty"` // (optional) the maximum number of concurrent workflow runs, default 1
|
||||
LimitStrategy ConcurrencyLimitStrategy `protobuf:"varint,3,opt,name=limit_strategy,json=limitStrategy,proto3,enum=ConcurrencyLimitStrategy" json:"limit_strategy,omitempty"` // (optional) the strategy to use when the concurrency limit is reached, default CANCEL_IN_PROGRESS
|
||||
Action *string `protobuf:"bytes,1,opt,name=action,proto3,oneof" json:"action,omitempty"` // (optional) the action id for getting the concurrency group
|
||||
MaxRuns *int32 `protobuf:"varint,2,opt,name=max_runs,json=maxRuns,proto3,oneof" json:"max_runs,omitempty"` // (optional) the maximum number of concurrent workflow runs, default 1
|
||||
LimitStrategy *ConcurrencyLimitStrategy `protobuf:"varint,3,opt,name=limit_strategy,json=limitStrategy,proto3,enum=ConcurrencyLimitStrategy,oneof" json:"limit_strategy,omitempty"` // (optional) the strategy to use when the concurrency limit is reached, default CANCEL_IN_PROGRESS
|
||||
Expression *string `protobuf:"bytes,4,opt,name=expression,proto3,oneof" json:"expression,omitempty"` // (optional) the expression to use for concurrency
|
||||
}
|
||||
|
||||
func (x *WorkflowConcurrencyOpts) Reset() {
|
||||
@@ -529,26 +530,33 @@ func (*WorkflowConcurrencyOpts) Descriptor() ([]byte, []int) {
|
||||
}
|
||||
|
||||
func (x *WorkflowConcurrencyOpts) GetAction() string {
|
||||
if x != nil {
|
||||
return x.Action
|
||||
if x != nil && x.Action != nil {
|
||||
return *x.Action
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *WorkflowConcurrencyOpts) GetMaxRuns() int32 {
|
||||
if x != nil {
|
||||
return x.MaxRuns
|
||||
if x != nil && x.MaxRuns != nil {
|
||||
return *x.MaxRuns
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *WorkflowConcurrencyOpts) GetLimitStrategy() ConcurrencyLimitStrategy {
|
||||
if x != nil {
|
||||
return x.LimitStrategy
|
||||
if x != nil && x.LimitStrategy != nil {
|
||||
return *x.LimitStrategy
|
||||
}
|
||||
return ConcurrencyLimitStrategy_CANCEL_IN_PROGRESS
|
||||
}
|
||||
|
||||
func (x *WorkflowConcurrencyOpts) GetExpression() string {
|
||||
if x != nil && x.Expression != nil {
|
||||
return *x.Expression
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// CreateWorkflowJobOpts represents options to create a workflow job.
|
||||
type CreateWorkflowJobOpts struct {
|
||||
state protoimpl.MessageState
|
||||
@@ -1544,212 +1552,219 @@ var file_workflows_proto_rawDesc = []byte{
|
||||
0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x6a, 0x6f, 0x62, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74,
|
||||
0x69, 0x63, 0x6b, 0x79, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x42, 0x13, 0x0a,
|
||||
0x11, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69,
|
||||
0x74, 0x79, 0x22, 0x8e, 0x01, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43,
|
||||
0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x74, 0x73, 0x12, 0x16,
|
||||
0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
|
||||
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x75,
|
||||
0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x52, 0x75, 0x6e,
|
||||
0x73, 0x12, 0x40, 0x0a, 0x0e, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74,
|
||||
0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x43, 0x6f, 0x6e, 0x63,
|
||||
0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x74, 0x72, 0x61,
|
||||
0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74,
|
||||
0x65, 0x67, 0x79, 0x22, 0x82, 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,
|
||||
0x74, 0x79, 0x22, 0xfc, 0x01, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x43,
|
||||
0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x74, 0x73, 0x12, 0x1b,
|
||||
0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
|
||||
0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x6d,
|
||||
0x61, 0x78, 0x5f, 0x72, 0x75, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52,
|
||||
0x07, 0x6d, 0x61, 0x78, 0x52, 0x75, 0x6e, 0x73, 0x88, 0x01, 0x01, 0x12, 0x45, 0x0a, 0x0e, 0x6c,
|
||||
0x69, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
|
||||
0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x48, 0x02,
|
||||
0x52, 0x0d, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x88,
|
||||
0x01, 0x01, 0x12, 0x23, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x61, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x75, 0x6e, 0x73, 0x42,
|
||||
0x11, 0x0a, 0x0f, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65,
|
||||
0x67, 0x79, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x22, 0x82, 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, 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,
|
||||
0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x93, 0x02, 0x0a, 0x13, 0x44, 0x65, 0x73, 0x69, 0x72,
|
||||
0x65, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1f,
|
||||
0x0a, 0x08, 0x73, 0x74, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x48, 0x00, 0x52, 0x08, 0x73, 0x74, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x88, 0x01, 0x01, 0x12,
|
||||
0x1f, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x05, 0x48, 0x01, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x88, 0x01, 0x01,
|
||||
0x12, 0x1f, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x08, 0x48, 0x02, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x88, 0x01,
|
||||
0x01, 0x12, 0x3b, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18,
|
||||
0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, 0x61,
|
||||
0x62, 0x65, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x48, 0x03, 0x52,
|
||||
0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x1b,
|
||||
0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x48, 0x04,
|
||||
0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f,
|
||||
0x73, 0x74, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x69, 0x6e, 0x74,
|
||||
0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,
|
||||
0x65, 0x64, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f,
|
||||
0x72, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0xb2, 0x03, 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, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20,
|
||||
0x03, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09,
|
||||
0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x08, 0x75, 0x73, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x74,
|
||||
0x72, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x72, 0x65, 0x74, 0x72,
|
||||
0x69, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x0b, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69,
|
||||
0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||
0x65, 0x53, 0x74, 0x65, 0x70, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x0a,
|
||||
0x72, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x4e, 0x0a, 0x0d, 0x77, 0x6f,
|
||||
0x72, 0x6b, 0x65, 0x72, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x29, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
|
||||
0x6f, 0x77, 0x53, 0x74, 0x65, 0x70, 0x4f, 0x70, 0x74, 0x73, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x65,
|
||||
0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x77, 0x6f,
|
||||
0x72, 0x6b, 0x65, 0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x55, 0x0a, 0x11, 0x57, 0x6f,
|
||||
0x72, 0x6b, 0x65, 0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
|
||||
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
|
||||
0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x14, 0x2e, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72,
|
||||
0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
||||
0x01, 0x22, 0x3d, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x74, 0x65, 0x70, 0x52,
|
||||
0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x6e,
|
||||
0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73,
|
||||
0x22, 0x16, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
|
||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xdc, 0x02, 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, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x73, 0x63, 0x68, 0x65,
|
||||
0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 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, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
|
||||
0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65,
|
||||
0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x70,
|
||||
0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x12, 0x70, 0x61,
|
||||
0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64,
|
||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
|
||||
0x53, 0x74, 0x65, 0x70, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b,
|
||||
0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||
0x05, 0x48, 0x02, 0x52, 0x0a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x88,
|
||||
0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x4b, 0x65,
|
||||
0x79, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f,
|
||||
0x69, 0x64, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74,
|
||||
0x65, 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x68,
|
||||
0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x68,
|
||||
0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0xe8, 0x01, 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, 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, 0xe4, 0x03, 0x0a, 0x16, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f,
|
||||
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 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, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x93, 0x02, 0x0a, 0x13, 0x44, 0x65, 0x73,
|
||||
0x69, 0x72, 0x65, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73,
|
||||
0x12, 0x1f, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x73, 0x74, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x88, 0x01,
|
||||
0x01, 0x12, 0x1f, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x88,
|
||||
0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x08, 0x48, 0x02, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64,
|
||||
0x88, 0x01, 0x01, 0x12, 0x3b, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f,
|
||||
0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72,
|
||||
0x4c, 0x61, 0x62, 0x65, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x48,
|
||||
0x03, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x88, 0x01, 0x01,
|
||||
0x12, 0x1b, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05,
|
||||
0x48, 0x04, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a,
|
||||
0x09, 0x5f, 0x73, 0x74, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x69,
|
||||
0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x72, 0x65, 0x71, 0x75,
|
||||
0x69, 0x72, 0x65, 0x64, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x61,
|
||||
0x74, 0x6f, 0x72, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0xb2,
|
||||
0x03, 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, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18,
|
||||
0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1b,
|
||||
0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x72,
|
||||
0x65, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x72, 0x65,
|
||||
0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x0b, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x69,
|
||||
0x6d, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x43, 0x72, 0x65,
|
||||
0x61, 0x74, 0x65, 0x53, 0x74, 0x65, 0x70, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74,
|
||||
0x52, 0x0a, 0x72, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x4e, 0x0a, 0x0d,
|
||||
0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x09, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b,
|
||||
0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x65, 0x70, 0x4f, 0x70, 0x74, 0x73, 0x2e, 0x57, 0x6f, 0x72,
|
||||
0x6b, 0x65, 0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c,
|
||||
0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x55, 0x0a, 0x11,
|
||||
0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72,
|
||||
0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
|
||||
0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x14, 0x2e, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x57, 0x6f, 0x72, 0x6b,
|
||||
0x65, 0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
|
||||
0x02, 0x38, 0x01, 0x22, 0x3d, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x74, 0x65,
|
||||
0x70, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
|
||||
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
|
||||
0x75, 0x6e, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x75, 0x6e, 0x69,
|
||||
0x74, 0x73, 0x22, 0x16, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
|
||||
0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xdc, 0x02, 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, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x73, 0x63,
|
||||
0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 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, 0x73, 0x63, 0x68, 0x65, 0x64,
|
||||
0x75, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x70, 0x61,
|
||||
0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52,
|
||||
0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x12,
|
||||
0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65,
|
||||
0x6e, 0x74, 0x53, 0x74, 0x65, 0x70, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x24,
|
||||
0x0a, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x06, 0x20,
|
||||
0x01, 0x28, 0x05, 0x48, 0x02, 0x52, 0x0a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65,
|
||||
0x78, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65,
|
||||
0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64,
|
||||
0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e,
|
||||
0x74, 0x5f, 0x69, 0x64, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f,
|
||||
0x73, 0x74, 0x65, 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f,
|
||||
0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x5f,
|
||||
0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0xe8, 0x01, 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, 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, 0xe4, 0x03, 0x0a, 0x16, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72,
|
||||
0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||
0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x70, 0x61, 0x72,
|
||||
0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08,
|
||||
0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x12, 0x70,
|
||||
0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69,
|
||||
0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e,
|
||||
0x74, 0x53, 0x74, 0x65, 0x70, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a,
|
||||
0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x05, 0x20, 0x01,
|
||||
0x28, 0x05, 0x48, 0x02, 0x52, 0x0a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78,
|
||||
0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79,
|
||||
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x4b,
|
||||
0x65, 0x79, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x13, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01,
|
||||
0x28, 0x09, 0x48, 0x04, 0x52, 0x12, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
|
||||
0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x64,
|
||||
0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x64,
|
||||
0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65,
|
||||
0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08,
|
||||
0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x48, 0x06,
|
||||
0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a,
|
||||
0x0a, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x42, 0x15, 0x0a, 0x13, 0x5f,
|
||||
0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f,
|
||||
0x69, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64,
|
||||
0x65, 0x78, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79,
|
||||
0x42, 0x16, 0x0a, 0x14, 0x5f, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f,
|
||||
0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x64, 0x65, 0x73,
|
||||
0x69, 0x72, 0x65, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x42, 0x0b,
|
||||
0x0a, 0x09, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x41, 0x0a, 0x17, 0x54,
|
||||
0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
|
||||
0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x22, 0x6d,
|
||||
0x0a, 0x13, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2e, 0x0a,
|
||||
0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32,
|
||||
0x12, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x44, 0x75, 0x72, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a,
|
||||
0x14, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x24, 0x0a, 0x0e, 0x53, 0x74, 0x69, 0x63, 0x6b, 0x79, 0x53,
|
||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x4f, 0x46, 0x54, 0x10,
|
||||
0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x41, 0x52, 0x44, 0x10, 0x01, 0x2a, 0x32, 0x0a, 0x0c, 0x57,
|
||||
0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0c, 0x0a, 0x08, 0x46,
|
||||
0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x55, 0x52,
|
||||
0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x44, 0x41, 0x47, 0x10, 0x02, 0x2a,
|
||||
0x6c, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69,
|
||||
0x6d, 0x69, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x16, 0x0a, 0x12, 0x43,
|
||||
0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, 0x49, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53,
|
||||
0x53, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x44, 0x52, 0x4f, 0x50, 0x5f, 0x4e, 0x45, 0x57, 0x45,
|
||||
0x53, 0x54, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x51, 0x55, 0x45, 0x55, 0x45, 0x5f, 0x4e, 0x45,
|
||||
0x57, 0x45, 0x53, 0x54, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f,
|
||||
0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x52, 0x4f, 0x42, 0x49, 0x4e, 0x10, 0x03, 0x2a, 0x85, 0x01,
|
||||
0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x43, 0x6f, 0x6d,
|
||||
0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x51, 0x55, 0x41, 0x4c,
|
||||
0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10,
|
||||
0x01, 0x12, 0x10, 0x0a, 0x0c, 0x47, 0x52, 0x45, 0x41, 0x54, 0x45, 0x52, 0x5f, 0x54, 0x48, 0x41,
|
||||
0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x47, 0x52, 0x45, 0x41, 0x54, 0x45, 0x52, 0x5f, 0x54,
|
||||
0x48, 0x41, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x0d,
|
||||
0x0a, 0x09, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x10, 0x04, 0x12, 0x16, 0x0a,
|
||||
0x12, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x45, 0x51,
|
||||
0x55, 0x41, 0x4c, 0x10, 0x05, 0x2a, 0x5d, 0x0a, 0x11, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d,
|
||||
0x69, 0x74, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x45,
|
||||
0x43, 0x4f, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x49, 0x4e, 0x55, 0x54, 0x45,
|
||||
0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x55, 0x52, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03,
|
||||
0x44, 0x41, 0x59, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x45, 0x45, 0x4b, 0x10, 0x04, 0x12,
|
||||
0x09, 0x0a, 0x05, 0x4d, 0x4f, 0x4e, 0x54, 0x48, 0x10, 0x05, 0x12, 0x08, 0x0a, 0x04, 0x59, 0x45,
|
||||
0x41, 0x52, 0x10, 0x06, 0x32, 0x8a, 0x02, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
|
||||
0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 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, 0x44,
|
||||
0x0a, 0x0f, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
|
||||
0x77, 0x12, 0x17, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66,
|
||||
0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x54, 0x72, 0x69,
|
||||
0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e,
|
||||
0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x70, 0x61,
|
||||
0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x12, 0x70, 0x61, 0x72,
|
||||
0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18,
|
||||
0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x53,
|
||||
0x74, 0x65, 0x70, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x63,
|
||||
0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05,
|
||||
0x48, 0x02, 0x52, 0x0a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x88, 0x01,
|
||||
0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06,
|
||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x4b, 0x65, 0x79,
|
||||
0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x13, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61,
|
||||
0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
|
||||
0x48, 0x04, 0x52, 0x12, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4d, 0x65,
|
||||
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x64, 0x65, 0x73,
|
||||
0x69, 0x72, 0x65, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08,
|
||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x05, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x57,
|
||||
0x6f, 0x72, 0x6b, 0x65, 0x72, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x72,
|
||||
0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x48, 0x06, 0x52, 0x08,
|
||||
0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f,
|
||||
0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x70, 0x61,
|
||||
0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64,
|
||||
0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78,
|
||||
0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x16,
|
||||
0x0a, 0x14, 0x5f, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65,
|
||||
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x64, 0x65, 0x73, 0x69, 0x72,
|
||||
0x65, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x42, 0x0b, 0x0a, 0x09,
|
||||
0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x41, 0x0a, 0x17, 0x54, 0x72, 0x69,
|
||||
0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0c, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c,
|
||||
0x69, 0x6d, 0x69, 0x74, 0x12, 0x14, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69,
|
||||
0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x50, 0x75, 0x74,
|
||||
0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 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,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
|
||||
0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77,
|
||||
0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x22, 0x6d, 0x0a, 0x13,
|
||||
0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2e, 0x0a, 0x08, 0x64,
|
||||
0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e,
|
||||
0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x50,
|
||||
0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x2a, 0x24, 0x0a, 0x0e, 0x53, 0x74, 0x69, 0x63, 0x6b, 0x79, 0x53, 0x74, 0x72,
|
||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x4f, 0x46, 0x54, 0x10, 0x00, 0x12,
|
||||
0x08, 0x0a, 0x04, 0x48, 0x41, 0x52, 0x44, 0x10, 0x01, 0x2a, 0x32, 0x0a, 0x0c, 0x57, 0x6f, 0x72,
|
||||
0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x55, 0x4e,
|
||||
0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x55, 0x52, 0x41, 0x42,
|
||||
0x4c, 0x45, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x44, 0x41, 0x47, 0x10, 0x02, 0x2a, 0x6c, 0x0a,
|
||||
0x18, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x6d, 0x69,
|
||||
0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x41, 0x4e,
|
||||
0x43, 0x45, 0x4c, 0x5f, 0x49, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10,
|
||||
0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x44, 0x52, 0x4f, 0x50, 0x5f, 0x4e, 0x45, 0x57, 0x45, 0x53, 0x54,
|
||||
0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x51, 0x55, 0x45, 0x55, 0x45, 0x5f, 0x4e, 0x45, 0x57, 0x45,
|
||||
0x53, 0x54, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x5f, 0x52, 0x4f,
|
||||
0x55, 0x4e, 0x44, 0x5f, 0x52, 0x4f, 0x42, 0x49, 0x4e, 0x10, 0x03, 0x2a, 0x85, 0x01, 0x0a, 0x15,
|
||||
0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x61,
|
||||
0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x00,
|
||||
0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x01, 0x12,
|
||||
0x10, 0x0a, 0x0c, 0x47, 0x52, 0x45, 0x41, 0x54, 0x45, 0x52, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x10,
|
||||
0x02, 0x12, 0x19, 0x0a, 0x15, 0x47, 0x52, 0x45, 0x41, 0x54, 0x45, 0x52, 0x5f, 0x54, 0x48, 0x41,
|
||||
0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x45, 0x51, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09,
|
||||
0x4c, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x4c,
|
||||
0x45, 0x53, 0x53, 0x5f, 0x54, 0x48, 0x41, 0x4e, 0x5f, 0x4f, 0x52, 0x5f, 0x45, 0x51, 0x55, 0x41,
|
||||
0x4c, 0x10, 0x05, 0x2a, 0x5d, 0x0a, 0x11, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74,
|
||||
0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x45, 0x43, 0x4f,
|
||||
0x4e, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x49, 0x4e, 0x55, 0x54, 0x45, 0x10, 0x01,
|
||||
0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x55, 0x52, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x44, 0x41,
|
||||
0x59, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x45, 0x45, 0x4b, 0x10, 0x04, 0x12, 0x09, 0x0a,
|
||||
0x05, 0x4d, 0x4f, 0x4e, 0x54, 0x48, 0x10, 0x05, 0x12, 0x08, 0x0a, 0x04, 0x59, 0x45, 0x41, 0x52,
|
||||
0x10, 0x06, 0x32, 0x8a, 0x02, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 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, 0x44, 0x0a, 0x0f,
|
||||
0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12,
|
||||
0x17, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
|
||||
0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67,
|
||||
0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0c, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d,
|
||||
0x69, 0x74, 0x12, 0x14, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69,
|
||||
0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x50, 0x75, 0x74, 0x52, 0x61,
|
||||
0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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 (
|
||||
@@ -2024,6 +2039,7 @@ func file_workflows_proto_init() {
|
||||
}
|
||||
}
|
||||
file_workflows_proto_msgTypes[1].OneofWrappers = []interface{}{}
|
||||
file_workflows_proto_msgTypes[2].OneofWrappers = []interface{}{}
|
||||
file_workflows_proto_msgTypes[4].OneofWrappers = []interface{}{}
|
||||
file_workflows_proto_msgTypes[8].OneofWrappers = []interface{}{}
|
||||
file_workflows_proto_msgTypes[12].OneofWrappers = []interface{}{}
|
||||
|
||||
@@ -457,6 +457,13 @@ func getCreateWorkflowOpts(req *contracts.PutWorkflowRequest) (*repository.Creat
|
||||
var concurrency *repository.CreateWorkflowConcurrencyOpts
|
||||
|
||||
if req.Opts.Concurrency != nil {
|
||||
if req.Opts.Concurrency.Action == nil && req.Opts.Concurrency.Expression == nil {
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
"concurrency action or expression is required",
|
||||
)
|
||||
}
|
||||
|
||||
var limitStrategy *string
|
||||
|
||||
if req.Opts.Concurrency.LimitStrategy.String() != "" {
|
||||
@@ -466,10 +473,8 @@ func getCreateWorkflowOpts(req *contracts.PutWorkflowRequest) (*repository.Creat
|
||||
concurrency = &repository.CreateWorkflowConcurrencyOpts{
|
||||
Action: req.Opts.Concurrency.Action,
|
||||
LimitStrategy: limitStrategy,
|
||||
}
|
||||
|
||||
if req.Opts.Concurrency.MaxRuns != 0 {
|
||||
concurrency.MaxRuns = &req.Opts.Concurrency.MaxRuns
|
||||
Expression: req.Opts.Concurrency.Expression,
|
||||
MaxRuns: req.Opts.Concurrency.MaxRuns,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -864,8 +864,8 @@ func (ec *JobsControllerImpl) queueStepRun(ctx context.Context, tenantId, stepId
|
||||
_, err = ec.repo.StepRun().QueueStepRun(ctx, tenantId, stepRunId, queueOpts)
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, repository.ErrStepRunIsNotPending) {
|
||||
ec.l.Debug().Msgf("step run %s is not pending, skipping scheduling", stepRunId)
|
||||
if errors.Is(err, repository.ErrAlreadyQueued) {
|
||||
ec.l.Debug().Msgf("step run %s is already queued, skipping scheduling", stepRunId)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/hatchet-dev/hatchet/internal/datautils"
|
||||
"github.com/hatchet-dev/hatchet/internal/msgqueue"
|
||||
"github.com/hatchet-dev/hatchet/internal/queueutils"
|
||||
"github.com/hatchet-dev/hatchet/internal/services/controllers/partition"
|
||||
"github.com/hatchet-dev/hatchet/internal/services/shared/recoveryutils"
|
||||
"github.com/hatchet-dev/hatchet/internal/services/shared/tasktypes"
|
||||
@@ -34,8 +35,8 @@ type queue struct {
|
||||
// a custom queue logger
|
||||
ql *zerolog.Logger
|
||||
|
||||
tenantQueueOperations sync.Map
|
||||
updateStepRunOperations sync.Map
|
||||
tenantQueueOperations *queueutils.OperationPool
|
||||
updateStepRunOperations *queueutils.OperationPool
|
||||
}
|
||||
|
||||
func newQueue(
|
||||
@@ -53,7 +54,7 @@ func newQueue(
|
||||
return nil, fmt.Errorf("could not create scheduler: %w", err)
|
||||
}
|
||||
|
||||
return &queue{
|
||||
q := &queue{
|
||||
mq: mq,
|
||||
l: l,
|
||||
repo: repo,
|
||||
@@ -62,95 +63,12 @@ func newQueue(
|
||||
a: a,
|
||||
p: p,
|
||||
ql: ql,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type operation struct {
|
||||
mu sync.RWMutex
|
||||
shouldContinue bool
|
||||
isRunning bool
|
||||
tenantId string
|
||||
lastRun time.Time
|
||||
description string
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
func (o *operation) runOrContinue(l *zerolog.Logger, ql *zerolog.Logger, scheduler func(context.Context, string) (bool, error)) {
|
||||
o.setContinue(true)
|
||||
o.run(l, ql, scheduler)
|
||||
}
|
||||
|
||||
func (o *operation) run(l *zerolog.Logger, ql *zerolog.Logger, scheduler func(context.Context, string) (bool, error)) {
|
||||
if !o.setRunning(true, ql) {
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
o.setRunning(false, ql)
|
||||
}()
|
||||
q.tenantQueueOperations = queueutils.NewOperationPool(ql, time.Second*5, "check tenant queue", q.scheduleStepRuns)
|
||||
q.updateStepRunOperations = queueutils.NewOperationPool(ql, time.Second*30, "update step runs", q.processStepRunUpdates)
|
||||
|
||||
f := func() {
|
||||
o.setContinue(false)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), o.timeout)
|
||||
defer cancel()
|
||||
|
||||
shouldContinue, err := scheduler(ctx, o.tenantId)
|
||||
|
||||
if err != nil {
|
||||
l.Err(err).Msgf("could not %s", o.description)
|
||||
return
|
||||
}
|
||||
|
||||
// if a continue was set during execution of the scheduler, we'd like to continue no matter what.
|
||||
// if a continue was not set, we'd like to set it to the value returned by the scheduler.
|
||||
if !o.getContinue() {
|
||||
o.setContinue(shouldContinue)
|
||||
}
|
||||
}
|
||||
|
||||
f()
|
||||
|
||||
for o.getContinue() {
|
||||
f()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// setRunning sets the running state of the operation and returns true if the state was changed,
|
||||
// false if the state was not changed.
|
||||
func (o *operation) setRunning(isRunning bool, ql *zerolog.Logger) bool {
|
||||
o.mu.Lock()
|
||||
defer o.mu.Unlock()
|
||||
|
||||
if isRunning == o.isRunning {
|
||||
return false
|
||||
}
|
||||
|
||||
if isRunning {
|
||||
ql.Info().Str("tenant_id", o.tenantId).TimeDiff("last_run", time.Now(), o.lastRun).Msg(o.description)
|
||||
|
||||
o.lastRun = time.Now()
|
||||
}
|
||||
|
||||
o.isRunning = isRunning
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *operation) setContinue(shouldContinue bool) {
|
||||
o.mu.Lock()
|
||||
defer o.mu.Unlock()
|
||||
|
||||
o.shouldContinue = shouldContinue
|
||||
}
|
||||
|
||||
func (o *operation) getContinue() bool {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
return o.shouldContinue
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (q *queue) Start() (func() error, error) {
|
||||
@@ -254,17 +172,8 @@ func (q *queue) handleCheckQueue(ctx context.Context, task *msgqueue.Message) er
|
||||
}
|
||||
|
||||
// if this tenant is registered, then we should check the queue
|
||||
if opInt, ok := q.tenantQueueOperations.Load(metadata.TenantId); ok {
|
||||
op := opInt.(*operation)
|
||||
|
||||
op.runOrContinue(q.l, q.ql, q.scheduleStepRuns)
|
||||
}
|
||||
|
||||
if opInt, ok := q.updateStepRunOperations.Load(metadata.TenantId); ok {
|
||||
op := opInt.(*operation)
|
||||
|
||||
op.runOrContinue(q.l, q.ql, q.processStepRunUpdates)
|
||||
}
|
||||
q.tenantQueueOperations.RunOrContinue(metadata.TenantId)
|
||||
q.updateStepRunOperations.RunOrContinue(metadata.TenantId)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -284,7 +193,7 @@ func (q *queue) runTenantQueues(ctx context.Context) func() {
|
||||
for i := range tenants {
|
||||
tenantId := sqlchelpers.UUIDToStr(tenants[i].ID)
|
||||
|
||||
q.getQueueOperation(tenantId).run(q.l, q.ql, q.scheduleStepRuns)
|
||||
q.tenantQueueOperations.RunOrContinue(tenantId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,40 +243,6 @@ func (q *queue) scheduleStepRuns(ctx context.Context, tenantId string) (bool, er
|
||||
return queueResults.Continue, err
|
||||
}
|
||||
|
||||
func (q *queue) getQueueOperation(tenantId string) *operation {
|
||||
op, ok := q.tenantQueueOperations.Load(tenantId)
|
||||
|
||||
if !ok {
|
||||
op = &operation{
|
||||
tenantId: tenantId,
|
||||
lastRun: time.Now(),
|
||||
description: "scheduling step runs",
|
||||
timeout: 30 * time.Second,
|
||||
}
|
||||
|
||||
q.tenantQueueOperations.Store(tenantId, op)
|
||||
}
|
||||
|
||||
return op.(*operation)
|
||||
}
|
||||
|
||||
func (q *queue) getUpdateStepRunOperation(tenantId string) *operation {
|
||||
op, ok := q.updateStepRunOperations.Load(tenantId)
|
||||
|
||||
if !ok {
|
||||
op = &operation{
|
||||
tenantId: tenantId,
|
||||
lastRun: time.Now(),
|
||||
description: "updating step runs",
|
||||
timeout: 300 * time.Second,
|
||||
}
|
||||
|
||||
q.updateStepRunOperations.Store(tenantId, op)
|
||||
}
|
||||
|
||||
return op.(*operation)
|
||||
}
|
||||
|
||||
func (q *queue) runTenantUpdateStepRuns(ctx context.Context) func() {
|
||||
return func() {
|
||||
q.l.Debug().Msgf("partition: updating step run statuses")
|
||||
@@ -383,7 +258,7 @@ func (q *queue) runTenantUpdateStepRuns(ctx context.Context) func() {
|
||||
for i := range tenants {
|
||||
tenantId := sqlchelpers.UUIDToStr(tenants[i].ID)
|
||||
|
||||
q.getUpdateStepRunOperation(tenantId).run(q.l, q.ql, q.processStepRunUpdates)
|
||||
q.updateStepRunOperations.RunOrContinue(tenantId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,11 @@ import (
|
||||
"github.com/rs/zerolog"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/internal/cel"
|
||||
"github.com/hatchet-dev/hatchet/internal/datautils"
|
||||
"github.com/hatchet-dev/hatchet/internal/integrations/alerting"
|
||||
"github.com/hatchet-dev/hatchet/internal/msgqueue"
|
||||
"github.com/hatchet-dev/hatchet/internal/queueutils"
|
||||
"github.com/hatchet-dev/hatchet/internal/services/controllers/partition"
|
||||
"github.com/hatchet-dev/hatchet/internal/services/shared/recoveryutils"
|
||||
"github.com/hatchet-dev/hatchet/internal/services/shared/tasktypes"
|
||||
@@ -30,14 +32,16 @@ type WorkflowsController interface {
|
||||
}
|
||||
|
||||
type WorkflowsControllerImpl struct {
|
||||
mq msgqueue.MessageQueue
|
||||
l *zerolog.Logger
|
||||
repo repository.EngineRepository
|
||||
dv datautils.DataDecoderValidator
|
||||
s gocron.Scheduler
|
||||
tenantAlerter *alerting.TenantAlertManager
|
||||
a *hatcheterrors.Wrapped
|
||||
p *partition.Partition
|
||||
mq msgqueue.MessageQueue
|
||||
l *zerolog.Logger
|
||||
repo repository.EngineRepository
|
||||
dv datautils.DataDecoderValidator
|
||||
s gocron.Scheduler
|
||||
tenantAlerter *alerting.TenantAlertManager
|
||||
a *hatcheterrors.Wrapped
|
||||
p *partition.Partition
|
||||
celParser *cel.CELParser
|
||||
processWorkflowEventsOps *queueutils.OperationPool
|
||||
}
|
||||
|
||||
type WorkflowsControllerOpt func(*WorkflowsControllerOpts)
|
||||
@@ -140,7 +144,7 @@ func New(fs ...WorkflowsControllerOpt) (*WorkflowsControllerImpl, error) {
|
||||
a := hatcheterrors.NewWrapped(opts.alerter)
|
||||
a.WithData(map[string]interface{}{"service": "workflows-controller"})
|
||||
|
||||
return &WorkflowsControllerImpl{
|
||||
w := &WorkflowsControllerImpl{
|
||||
mq: opts.mq,
|
||||
l: opts.l,
|
||||
repo: opts.repo,
|
||||
@@ -149,7 +153,12 @@ func New(fs ...WorkflowsControllerOpt) (*WorkflowsControllerImpl, error) {
|
||||
tenantAlerter: opts.ta,
|
||||
a: a,
|
||||
p: opts.p,
|
||||
}, nil
|
||||
celParser: cel.NewCELParser(),
|
||||
}
|
||||
|
||||
w.processWorkflowEventsOps = queueutils.NewOperationPool(w.l, time.Second*5, "process workflow events", w.processWorkflowEvents)
|
||||
|
||||
return w, nil
|
||||
}
|
||||
|
||||
func (wc *WorkflowsControllerImpl) Start() (func() error, error) {
|
||||
@@ -195,6 +204,18 @@ func (wc *WorkflowsControllerImpl) Start() (func() error, error) {
|
||||
return nil, fmt.Errorf("could not poll active queues: %w", err)
|
||||
}
|
||||
|
||||
_, err = wc.s.NewJob(
|
||||
gocron.DurationJob(time.Second*1),
|
||||
gocron.NewTask(
|
||||
wc.runTenantProcessWorkflowRunEvents(ctx),
|
||||
),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, fmt.Errorf("could not schedule process workflow run events: %w", err)
|
||||
}
|
||||
|
||||
wc.s.Start()
|
||||
|
||||
f := func(task *msgqueue.Message) error {
|
||||
@@ -531,3 +552,39 @@ func (wc *WorkflowsControllerImpl) cancelGetGroupKeyRun(ctx context.Context, ten
|
||||
|
||||
return wc.cancelWorkflowRunJobs(ctx, workflowRun)
|
||||
}
|
||||
|
||||
func (wc *WorkflowsControllerImpl) runTenantProcessWorkflowRunEvents(ctx context.Context) func() {
|
||||
return func() {
|
||||
wc.l.Debug().Msgf("partition: processing workflow run events")
|
||||
|
||||
// list all tenants
|
||||
tenants, err := wc.repo.Tenant().ListTenantsByControllerPartition(ctx, wc.p.GetControllerPartitionId())
|
||||
|
||||
if err != nil {
|
||||
wc.l.Err(err).Msg("could not list tenants")
|
||||
return
|
||||
}
|
||||
|
||||
for i := range tenants {
|
||||
tenantId := sqlchelpers.UUIDToStr(tenants[i].ID)
|
||||
|
||||
wc.processWorkflowEventsOps.RunOrContinue(tenantId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wc *WorkflowsControllerImpl) processWorkflowEvents(ctx context.Context, tenantId string) (bool, error) {
|
||||
ctx, span := telemetry.NewSpan(ctx, "process-workflow-events")
|
||||
defer span.End()
|
||||
|
||||
dbCtx, cancel := context.WithTimeout(ctx, 300*time.Second)
|
||||
defer cancel()
|
||||
|
||||
res, err := wc.repo.WorkflowRun().ProcessWorkflowRunUpdates(dbCtx, tenantId)
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("could not process step run updates: %w", err)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package workflows
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/internal/cel"
|
||||
"github.com/hatchet-dev/hatchet/internal/datautils"
|
||||
"github.com/hatchet-dev/hatchet/internal/msgqueue"
|
||||
"github.com/hatchet-dev/hatchet/internal/services/shared/tasktypes"
|
||||
@@ -36,6 +38,7 @@ func (wc *WorkflowsControllerImpl) handleWorkflowRunQueued(ctx context.Context,
|
||||
err = wc.dv.DecodeAndValidate(task.Metadata, &metadata)
|
||||
|
||||
if err != nil {
|
||||
|
||||
return fmt.Errorf("could not decode job task metadata: %w", err)
|
||||
}
|
||||
|
||||
@@ -76,7 +79,30 @@ func (wc *WorkflowsControllerImpl) handleWorkflowRunQueued(ctx context.Context,
|
||||
}
|
||||
|
||||
return nil
|
||||
} else if workflowRun.ConcurrencyLimitStrategy.Valid && !workflowRun.GetGroupKeyRunId.Valid {
|
||||
} else if workflowRun.ConcurrencyLimitStrategy.Valid && workflowRun.ConcurrencyGroupExpression.Valid {
|
||||
// if the workflow has a concurrency group expression, then we need to evaluate it
|
||||
// and see if we can start the workflow run
|
||||
wc.l.Info().Msgf("workflow %s has concurrency settings", workflowRunId)
|
||||
|
||||
groupKey, err := wc.evalWorkflowRunConcurrency(ctx, metadata.TenantId, workflowRunId, workflowRun.ConcurrencyGroupExpression.String)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not evaluate concurrency group expression: %w", err)
|
||||
}
|
||||
|
||||
if groupKey == nil {
|
||||
// fail the workflow run
|
||||
workflowRun, err := wc.repo.WorkflowRun().GetWorkflowRunById(ctx, metadata.TenantId, workflowRunId)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get workflow run: %w", err)
|
||||
}
|
||||
|
||||
return wc.cancelWorkflowRunJobs(ctx, workflowRun)
|
||||
}
|
||||
|
||||
return wc.bumpQueue(ctx, metadata.TenantId, sqlchelpers.UUIDToStr(workflowRun.WorkflowVersion.ID), groupKey)
|
||||
} else if workflowRun.ConcurrencyLimitStrategy.Valid {
|
||||
return fmt.Errorf("workflow run %s has concurrency settings but no group key run", workflowRunId)
|
||||
}
|
||||
|
||||
@@ -89,6 +115,54 @@ func (wc *WorkflowsControllerImpl) handleWorkflowRunQueued(ctx context.Context,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wc *WorkflowsControllerImpl) evalWorkflowRunConcurrency(ctx context.Context, tenantId, workflowRunId, expr string) (*string, error) {
|
||||
input, err := wc.repo.WorkflowRun().GetWorkflowRunInputData(tenantId, workflowRunId)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get workflow run input data: %w", err)
|
||||
}
|
||||
|
||||
addMetaRes, err := wc.repo.WorkflowRun().GetWorkflowRunAdditionalMeta(ctx, tenantId, workflowRunId)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get workflow run additional meta: %w", err)
|
||||
}
|
||||
|
||||
addMeta := map[string]interface{}{}
|
||||
|
||||
if addMetaRes.AdditionalMetadata != nil {
|
||||
err = json.Unmarshal(addMetaRes.AdditionalMetadata, &addMeta)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not decode additional metadata: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
concurrencyGroupId, err := wc.celParser.ParseAndEvalWorkflowString(expr, cel.NewWorkflowStringInput(
|
||||
cel.WithInput(input),
|
||||
cel.WithAdditionalMetadata(addMeta),
|
||||
cel.WithWorkflowRunID(workflowRunId),
|
||||
))
|
||||
|
||||
opts := &repository.UpdateWorkflowRunFromGroupKeyEvalOpts{}
|
||||
|
||||
if err != nil {
|
||||
opts.Error = repository.StringPtr(fmt.Sprintf("could not evaluate concurrency group expression %s: %s", expr, err.Error()))
|
||||
|
||||
wc.l.Err(err).Msgf("could not evaluate concurrency group expression for tenant %s and workflow run %s", tenantId, workflowRunId)
|
||||
} else {
|
||||
opts.GroupKey = repository.StringPtr(concurrencyGroupId)
|
||||
}
|
||||
|
||||
err = wc.repo.WorkflowRun().UpdateWorkflowRunFromGroupKeyEval(ctx, tenantId, workflowRunId, opts)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not update workflow run from group key eval: %w", err)
|
||||
}
|
||||
|
||||
return opts.GroupKey, nil
|
||||
}
|
||||
|
||||
func (wc *WorkflowsControllerImpl) handleWorkflowRunFinished(ctx context.Context, task *msgqueue.Message) error {
|
||||
ctx, span := telemetry.NewSpan(ctx, "handle-workflow-run-finished")
|
||||
defer span.End()
|
||||
|
||||
@@ -500,6 +500,8 @@ func (d *DispatcherImpl) handleStepRunAssignedTask(ctx context.Context, task *ms
|
||||
}
|
||||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
|
||||
if success {
|
||||
defer d.repo.StepRun().DeferredStepRunEvent(
|
||||
metadata.TenantId,
|
||||
@@ -508,6 +510,8 @@ func (d *DispatcherImpl) handleStepRunAssignedTask(ctx context.Context, task *ms
|
||||
EventMessage: repository.StringPtr("Sent step run to the assigned worker"),
|
||||
EventReason: repository.StepRunEventReasonPtr(dbsqlc.StepRunEventReasonSENTTOWORKER),
|
||||
EventSeverity: repository.StepRunEventSeverityPtr(dbsqlc.StepRunEventSeverityINFO),
|
||||
Timestamp: &now,
|
||||
EventData: map[string]interface{}{"worker_id": payload.WorkerId},
|
||||
},
|
||||
)
|
||||
|
||||
@@ -521,6 +525,8 @@ func (d *DispatcherImpl) handleStepRunAssignedTask(ctx context.Context, task *ms
|
||||
EventMessage: repository.StringPtr("Could not send step run to assigned worker"),
|
||||
EventReason: repository.StepRunEventReasonPtr(dbsqlc.StepRunEventReasonREASSIGNED),
|
||||
EventSeverity: repository.StepRunEventSeverityPtr(dbsqlc.StepRunEventSeverityWARNING),
|
||||
Timestamp: &now,
|
||||
EventData: map[string]interface{}{"worker_id": payload.WorkerId},
|
||||
},
|
||||
)
|
||||
|
||||
@@ -529,7 +535,7 @@ func (d *DispatcherImpl) handleStepRunAssignedTask(ctx context.Context, task *ms
|
||||
IsInternalRetry: true,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
if err != nil && !errors.Is(err, repository.ErrAlreadyRunning) {
|
||||
multiErr = multierror.Append(multiErr, fmt.Errorf("💥 could not requeue step run in dispatcher: %w", err))
|
||||
}
|
||||
|
||||
|
||||
+11
-5
@@ -303,21 +303,27 @@ func (a *adminClientImpl) getPutRequest(workflow *types.Workflow) (*admincontrac
|
||||
|
||||
if workflow.Concurrency != nil {
|
||||
opts.Concurrency = &admincontracts.WorkflowConcurrencyOpts{
|
||||
Action: workflow.Concurrency.ActionID,
|
||||
Action: workflow.Concurrency.ActionID,
|
||||
Expression: workflow.Concurrency.Expression,
|
||||
}
|
||||
|
||||
var limitStrat admincontracts.ConcurrencyLimitStrategy
|
||||
|
||||
switch workflow.Concurrency.LimitStrategy {
|
||||
case types.CancelInProgress:
|
||||
opts.Concurrency.LimitStrategy = admincontracts.ConcurrencyLimitStrategy_CANCEL_IN_PROGRESS
|
||||
limitStrat = admincontracts.ConcurrencyLimitStrategy_CANCEL_IN_PROGRESS
|
||||
case types.GroupRoundRobin:
|
||||
opts.Concurrency.LimitStrategy = admincontracts.ConcurrencyLimitStrategy_GROUP_ROUND_ROBIN
|
||||
limitStrat = admincontracts.ConcurrencyLimitStrategy_GROUP_ROUND_ROBIN
|
||||
default:
|
||||
opts.Concurrency.LimitStrategy = admincontracts.ConcurrencyLimitStrategy_CANCEL_IN_PROGRESS
|
||||
limitStrat = admincontracts.ConcurrencyLimitStrategy_CANCEL_IN_PROGRESS
|
||||
}
|
||||
|
||||
opts.Concurrency.LimitStrategy = &limitStrat
|
||||
|
||||
// TODO: should be a pointer because users might want to set maxRuns temporarily for disabling
|
||||
if workflow.Concurrency.MaxRuns != 0 {
|
||||
opts.Concurrency.MaxRuns = workflow.Concurrency.MaxRuns
|
||||
maxRuns := workflow.Concurrency.MaxRuns
|
||||
opts.Concurrency.MaxRuns = &maxRuns
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-15
@@ -64,20 +64,22 @@ const (
|
||||
|
||||
// Defines values for StepRunEventReason.
|
||||
const (
|
||||
StepRunEventReasonASSIGNED StepRunEventReason = "ASSIGNED"
|
||||
StepRunEventReasonCANCELLED StepRunEventReason = "CANCELLED"
|
||||
StepRunEventReasonFAILED StepRunEventReason = "FAILED"
|
||||
StepRunEventReasonFINISHED StepRunEventReason = "FINISHED"
|
||||
StepRunEventReasonREASSIGNED StepRunEventReason = "REASSIGNED"
|
||||
StepRunEventReasonREQUEUEDNOWORKER StepRunEventReason = "REQUEUED_NO_WORKER"
|
||||
StepRunEventReasonREQUEUEDRATELIMIT StepRunEventReason = "REQUEUED_RATE_LIMIT"
|
||||
StepRunEventReasonRETRIEDBYUSER StepRunEventReason = "RETRIED_BY_USER"
|
||||
StepRunEventReasonRETRYING StepRunEventReason = "RETRYING"
|
||||
StepRunEventReasonSCHEDULINGTIMEDOUT StepRunEventReason = "SCHEDULING_TIMED_OUT"
|
||||
StepRunEventReasonSLOTRELEASED StepRunEventReason = "SLOT_RELEASED"
|
||||
StepRunEventReasonSTARTED StepRunEventReason = "STARTED"
|
||||
StepRunEventReasonTIMEDOUT StepRunEventReason = "TIMED_OUT"
|
||||
StepRunEventReasonTIMEOUTREFRESHED StepRunEventReason = "TIMEOUT_REFRESHED"
|
||||
StepRunEventReasonASSIGNED StepRunEventReason = "ASSIGNED"
|
||||
StepRunEventReasonCANCELLED StepRunEventReason = "CANCELLED"
|
||||
StepRunEventReasonFAILED StepRunEventReason = "FAILED"
|
||||
StepRunEventReasonFINISHED StepRunEventReason = "FINISHED"
|
||||
StepRunEventReasonREASSIGNED StepRunEventReason = "REASSIGNED"
|
||||
StepRunEventReasonREQUEUEDNOWORKER StepRunEventReason = "REQUEUED_NO_WORKER"
|
||||
StepRunEventReasonREQUEUEDRATELIMIT StepRunEventReason = "REQUEUED_RATE_LIMIT"
|
||||
StepRunEventReasonRETRIEDBYUSER StepRunEventReason = "RETRIED_BY_USER"
|
||||
StepRunEventReasonRETRYING StepRunEventReason = "RETRYING"
|
||||
StepRunEventReasonSCHEDULINGTIMEDOUT StepRunEventReason = "SCHEDULING_TIMED_OUT"
|
||||
StepRunEventReasonSLOTRELEASED StepRunEventReason = "SLOT_RELEASED"
|
||||
StepRunEventReasonSTARTED StepRunEventReason = "STARTED"
|
||||
StepRunEventReasonTIMEDOUT StepRunEventReason = "TIMED_OUT"
|
||||
StepRunEventReasonTIMEOUTREFRESHED StepRunEventReason = "TIMEOUT_REFRESHED"
|
||||
StepRunEventReasonWORKFLOWRUNGROUPKEYFAILED StepRunEventReason = "WORKFLOW_RUN_GROUP_KEY_FAILED"
|
||||
StepRunEventReasonWORKFLOWRUNGROUPKEYSUCCEEDED StepRunEventReason = "WORKFLOW_RUN_GROUP_KEY_SUCCEEDED"
|
||||
)
|
||||
|
||||
// Defines values for StepRunEventSeverity.
|
||||
@@ -666,9 +668,10 @@ type StepRunEvent struct {
|
||||
Message string `json:"message"`
|
||||
Reason StepRunEventReason `json:"reason"`
|
||||
Severity StepRunEventSeverity `json:"severity"`
|
||||
StepRunId string `json:"stepRunId"`
|
||||
StepRunId *string `json:"stepRunId,omitempty"`
|
||||
TimeFirstSeen time.Time `json:"timeFirstSeen"`
|
||||
TimeLastSeen time.Time `json:"timeLastSeen"`
|
||||
WorkflowRunId *string `json:"workflowRunId,omitempty"`
|
||||
}
|
||||
|
||||
// StepRunEventList defines model for StepRunEventList.
|
||||
|
||||
@@ -48,7 +48,9 @@ const (
|
||||
)
|
||||
|
||||
type WorkflowConcurrency struct {
|
||||
ActionID string `yaml:"action,omitempty"`
|
||||
ActionID *string `yaml:"action,omitempty"`
|
||||
|
||||
Expression *string `yaml:"expression,omitempty"`
|
||||
|
||||
MaxRuns int32 `yaml:"maxRuns,omitempty"`
|
||||
|
||||
|
||||
+1087
-1596
File diff suppressed because it is too large
Load Diff
@@ -60,6 +60,7 @@ type InternalQueue string
|
||||
const (
|
||||
InternalQueueWORKERSEMAPHORECOUNT InternalQueue = "WORKER_SEMAPHORE_COUNT"
|
||||
InternalQueueSTEPRUNUPDATE InternalQueue = "STEP_RUN_UPDATE"
|
||||
InternalQueueWORKFLOWRUNUPDATE InternalQueue = "WORKFLOW_RUN_UPDATE"
|
||||
)
|
||||
|
||||
func (e *InternalQueue) Scan(src interface{}) error {
|
||||
@@ -319,21 +320,23 @@ func (ns NullLogLineLevel) Value() (driver.Value, error) {
|
||||
type StepRunEventReason string
|
||||
|
||||
const (
|
||||
StepRunEventReasonREQUEUEDNOWORKER StepRunEventReason = "REQUEUED_NO_WORKER"
|
||||
StepRunEventReasonREQUEUEDRATELIMIT StepRunEventReason = "REQUEUED_RATE_LIMIT"
|
||||
StepRunEventReasonSCHEDULINGTIMEDOUT StepRunEventReason = "SCHEDULING_TIMED_OUT"
|
||||
StepRunEventReasonASSIGNED StepRunEventReason = "ASSIGNED"
|
||||
StepRunEventReasonSTARTED StepRunEventReason = "STARTED"
|
||||
StepRunEventReasonFINISHED StepRunEventReason = "FINISHED"
|
||||
StepRunEventReasonFAILED StepRunEventReason = "FAILED"
|
||||
StepRunEventReasonRETRYING StepRunEventReason = "RETRYING"
|
||||
StepRunEventReasonCANCELLED StepRunEventReason = "CANCELLED"
|
||||
StepRunEventReasonTIMEDOUT StepRunEventReason = "TIMED_OUT"
|
||||
StepRunEventReasonREASSIGNED StepRunEventReason = "REASSIGNED"
|
||||
StepRunEventReasonSLOTRELEASED StepRunEventReason = "SLOT_RELEASED"
|
||||
StepRunEventReasonTIMEOUTREFRESHED StepRunEventReason = "TIMEOUT_REFRESHED"
|
||||
StepRunEventReasonRETRIEDBYUSER StepRunEventReason = "RETRIED_BY_USER"
|
||||
StepRunEventReasonSENTTOWORKER StepRunEventReason = "SENT_TO_WORKER"
|
||||
StepRunEventReasonREQUEUEDNOWORKER StepRunEventReason = "REQUEUED_NO_WORKER"
|
||||
StepRunEventReasonREQUEUEDRATELIMIT StepRunEventReason = "REQUEUED_RATE_LIMIT"
|
||||
StepRunEventReasonSCHEDULINGTIMEDOUT StepRunEventReason = "SCHEDULING_TIMED_OUT"
|
||||
StepRunEventReasonASSIGNED StepRunEventReason = "ASSIGNED"
|
||||
StepRunEventReasonSTARTED StepRunEventReason = "STARTED"
|
||||
StepRunEventReasonFINISHED StepRunEventReason = "FINISHED"
|
||||
StepRunEventReasonFAILED StepRunEventReason = "FAILED"
|
||||
StepRunEventReasonRETRYING StepRunEventReason = "RETRYING"
|
||||
StepRunEventReasonCANCELLED StepRunEventReason = "CANCELLED"
|
||||
StepRunEventReasonTIMEDOUT StepRunEventReason = "TIMED_OUT"
|
||||
StepRunEventReasonREASSIGNED StepRunEventReason = "REASSIGNED"
|
||||
StepRunEventReasonSLOTRELEASED StepRunEventReason = "SLOT_RELEASED"
|
||||
StepRunEventReasonTIMEOUTREFRESHED StepRunEventReason = "TIMEOUT_REFRESHED"
|
||||
StepRunEventReasonRETRIEDBYUSER StepRunEventReason = "RETRIED_BY_USER"
|
||||
StepRunEventReasonSENTTOWORKER StepRunEventReason = "SENT_TO_WORKER"
|
||||
StepRunEventReasonWORKFLOWRUNGROUPKEYSUCCEEDED StepRunEventReason = "WORKFLOW_RUN_GROUP_KEY_SUCCEEDED"
|
||||
StepRunEventReasonWORKFLOWRUNGROUPKEYFAILED StepRunEventReason = "WORKFLOW_RUN_GROUP_KEY_FAILED"
|
||||
)
|
||||
|
||||
func (e *StepRunEventReason) Scan(src interface{}) error {
|
||||
@@ -1146,6 +1149,7 @@ type StepRunEvent struct {
|
||||
Message string `json:"message"`
|
||||
Count int32 `json:"count"`
|
||||
Data []byte `json:"data"`
|
||||
WorkflowRunId pgtype.UUID `json:"workflowRunId"`
|
||||
}
|
||||
|
||||
type StepRunOrder struct {
|
||||
@@ -1407,13 +1411,14 @@ type Workflow struct {
|
||||
}
|
||||
|
||||
type WorkflowConcurrency struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
CreatedAt pgtype.Timestamp `json:"createdAt"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updatedAt"`
|
||||
WorkflowVersionId pgtype.UUID `json:"workflowVersionId"`
|
||||
GetConcurrencyGroupId pgtype.UUID `json:"getConcurrencyGroupId"`
|
||||
MaxRuns int32 `json:"maxRuns"`
|
||||
LimitStrategy ConcurrencyLimitStrategy `json:"limitStrategy"`
|
||||
ID pgtype.UUID `json:"id"`
|
||||
CreatedAt pgtype.Timestamp `json:"createdAt"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updatedAt"`
|
||||
WorkflowVersionId pgtype.UUID `json:"workflowVersionId"`
|
||||
GetConcurrencyGroupId pgtype.UUID `json:"getConcurrencyGroupId"`
|
||||
MaxRuns int32 `json:"maxRuns"`
|
||||
LimitStrategy ConcurrencyLimitStrategy `json:"limitStrategy"`
|
||||
ConcurrencyGroupExpression pgtype.Text `json:"concurrencyGroupExpression"`
|
||||
}
|
||||
|
||||
type WorkflowRun struct {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
CREATE TYPE "ConcurrencyLimitStrategy" AS ENUM ('CANCEL_IN_PROGRESS', 'DROP_NEWEST', 'QUEUE_NEWEST', 'GROUP_ROUND_ROBIN');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "InternalQueue" AS ENUM ('WORKER_SEMAPHORE_COUNT', 'STEP_RUN_UPDATE');
|
||||
CREATE TYPE "InternalQueue" AS ENUM ('WORKER_SEMAPHORE_COUNT', 'STEP_RUN_UPDATE', 'WORKFLOW_RUN_UPDATE');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "InviteLinkStatus" AS ENUM ('PENDING', 'ACCEPTED', 'REJECTED');
|
||||
@@ -20,7 +20,7 @@ CREATE TYPE "LimitResource" AS ENUM ('WORKFLOW_RUN', 'EVENT', 'WORKER', 'CRON',
|
||||
CREATE TYPE "LogLineLevel" AS ENUM ('DEBUG', 'INFO', 'WARN', 'ERROR');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "StepRunEventReason" AS ENUM ('REQUEUED_NO_WORKER', 'REQUEUED_RATE_LIMIT', 'SCHEDULING_TIMED_OUT', 'ASSIGNED', 'STARTED', 'FINISHED', 'FAILED', 'RETRYING', 'CANCELLED', 'TIMED_OUT', 'REASSIGNED', 'SLOT_RELEASED', 'TIMEOUT_REFRESHED', 'RETRIED_BY_USER', 'SENT_TO_WORKER');
|
||||
CREATE TYPE "StepRunEventReason" AS ENUM ('REQUEUED_NO_WORKER', 'REQUEUED_RATE_LIMIT', 'SCHEDULING_TIMED_OUT', 'ASSIGNED', 'STARTED', 'FINISHED', 'FAILED', 'RETRYING', 'CANCELLED', 'TIMED_OUT', 'REASSIGNED', 'SLOT_RELEASED', 'TIMEOUT_REFRESHED', 'RETRIED_BY_USER', 'SENT_TO_WORKER', 'WORKFLOW_RUN_GROUP_KEY_SUCCEEDED', 'WORKFLOW_RUN_GROUP_KEY_FAILED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "StepRunEventSeverity" AS ENUM ('INFO', 'WARNING', 'CRITICAL');
|
||||
@@ -396,12 +396,13 @@ CREATE TABLE "StepRunEvent" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"timeFirstSeen" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"timeLastSeen" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"stepRunId" UUID NOT NULL,
|
||||
"stepRunId" UUID,
|
||||
"reason" "StepRunEventReason" NOT NULL,
|
||||
"severity" "StepRunEventSeverity" NOT NULL,
|
||||
"message" TEXT NOT NULL,
|
||||
"count" INTEGER NOT NULL,
|
||||
"data" JSONB
|
||||
"data" JSONB,
|
||||
"workflowRunId" UUID
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
@@ -736,6 +737,7 @@ CREATE TABLE "WorkflowConcurrency" (
|
||||
"getConcurrencyGroupId" UUID,
|
||||
"maxRuns" INTEGER NOT NULL DEFAULT 1,
|
||||
"limitStrategy" "ConcurrencyLimitStrategy" NOT NULL DEFAULT 'CANCEL_IN_PROGRESS',
|
||||
"concurrencyGroupExpression" TEXT,
|
||||
|
||||
CONSTRAINT "WorkflowConcurrency_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
@@ -1074,6 +1076,9 @@ CREATE UNIQUE INDEX "StepRunEvent_id_key" ON "StepRunEvent"("id" ASC);
|
||||
-- CreateIndex
|
||||
CREATE INDEX "StepRunEvent_stepRunId_idx" ON "StepRunEvent"("stepRunId" ASC);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "StepRunEvent_workflowRunId_idx" ON "StepRunEvent"("workflowRunId" ASC);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "StepRunResultArchive_id_key" ON "StepRunResultArchive"("id" ASC);
|
||||
|
||||
@@ -1422,9 +1427,6 @@ ALTER TABLE "StepRun" ADD CONSTRAINT "StepRun_tickerId_fkey" FOREIGN KEY ("ticke
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "StepRun" ADD CONSTRAINT "StepRun_workerId_fkey" FOREIGN KEY ("workerId") REFERENCES "Worker"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "StepRunEvent" ADD CONSTRAINT "StepRunEvent_stepRunId_fkey" FOREIGN KEY ("stepRunId") REFERENCES "StepRun"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "StepRunResultArchive" ADD CONSTRAINT "StepRunResultArchive_stepRunId_fkey" FOREIGN KEY ("stepRunId") REFERENCES "StepRun"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
|
||||
@@ -474,6 +474,16 @@ deleted_sqis AS (
|
||||
sqi."stepRunId" = srs."id"
|
||||
AND sqi."workerId" = srs."workerId"
|
||||
),
|
||||
deleted_tqis AS (
|
||||
DELETE FROM
|
||||
"TimeoutQueueItem" tqi
|
||||
-- delete when step run id AND retry count tuples match
|
||||
USING
|
||||
step_runs_to_reassign srs
|
||||
WHERE
|
||||
tqi."stepRunId" = srs."id"
|
||||
AND tqi."retryCount" = srs."retryCount"
|
||||
),
|
||||
inserted_queue_items AS (
|
||||
INSERT INTO "QueueItem" (
|
||||
"stepRunId",
|
||||
@@ -546,7 +556,6 @@ RETURNING *;
|
||||
WITH oldsr AS (
|
||||
SELECT
|
||||
"id",
|
||||
"workerId",
|
||||
"retryCount"
|
||||
FROM
|
||||
"StepRun"
|
||||
|
||||
@@ -183,7 +183,7 @@ updated AS (
|
||||
ORDER BY "id" DESC
|
||||
LIMIT 1
|
||||
)
|
||||
RETURNING "StepRunEvent".id, "StepRunEvent"."timeFirstSeen", "StepRunEvent"."timeLastSeen", "StepRunEvent"."stepRunId", "StepRunEvent".reason, "StepRunEvent".severity, "StepRunEvent".message, "StepRunEvent".count, "StepRunEvent".data
|
||||
RETURNING "StepRunEvent".id, "StepRunEvent"."timeFirstSeen", "StepRunEvent"."timeLastSeen", "StepRunEvent"."stepRunId", "StepRunEvent".reason, "StepRunEvent".severity, "StepRunEvent".message, "StepRunEvent".count, "StepRunEvent".data, "StepRunEvent"."workflowRunId"
|
||||
)
|
||||
INSERT INTO "StepRunEvent" (
|
||||
"timeFirstSeen",
|
||||
@@ -514,7 +514,7 @@ updated AS (
|
||||
ORDER BY "id" DESC
|
||||
LIMIT 1
|
||||
)
|
||||
RETURNING "StepRunEvent".id, "StepRunEvent"."timeFirstSeen", "StepRunEvent"."timeLastSeen", "StepRunEvent"."stepRunId", "StepRunEvent".reason, "StepRunEvent".severity, "StepRunEvent".message, "StepRunEvent".count, "StepRunEvent".data
|
||||
RETURNING "StepRunEvent".id, "StepRunEvent"."timeFirstSeen", "StepRunEvent"."timeLastSeen", "StepRunEvent"."stepRunId", "StepRunEvent".reason, "StepRunEvent".severity, "StepRunEvent".message, "StepRunEvent".count, "StepRunEvent".data, "StepRunEvent"."workflowRunId"
|
||||
)
|
||||
INSERT INTO "StepRunEvent" (
|
||||
"timeFirstSeen",
|
||||
@@ -1525,7 +1525,7 @@ func (q *Queries) ListStepRunArchives(ctx context.Context, db DBTX, arg ListStep
|
||||
|
||||
const listStepRunEvents = `-- name: ListStepRunEvents :many
|
||||
SELECT
|
||||
id, "timeFirstSeen", "timeLastSeen", "stepRunId", reason, severity, message, count, data
|
||||
id, "timeFirstSeen", "timeLastSeen", "stepRunId", reason, severity, message, count, data, "workflowRunId"
|
||||
FROM
|
||||
"StepRunEvent"
|
||||
WHERE
|
||||
@@ -1563,6 +1563,7 @@ func (q *Queries) ListStepRunEvents(ctx context.Context, db DBTX, arg ListStepRu
|
||||
&i.Message,
|
||||
&i.Count,
|
||||
&i.Data,
|
||||
&i.WorkflowRunId,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1576,7 +1577,7 @@ func (q *Queries) ListStepRunEvents(ctx context.Context, db DBTX, arg ListStepRu
|
||||
|
||||
const listStepRunEventsByWorkflowRunId = `-- name: ListStepRunEventsByWorkflowRunId :many
|
||||
SELECT
|
||||
sre.id, sre."timeFirstSeen", sre."timeLastSeen", sre."stepRunId", sre.reason, sre.severity, sre.message, sre.count, sre.data
|
||||
sre.id, sre."timeFirstSeen", sre."timeLastSeen", sre."stepRunId", sre.reason, sre.severity, sre.message, sre.count, sre.data, sre."workflowRunId"
|
||||
FROM
|
||||
"StepRunEvent" sre
|
||||
JOIN
|
||||
@@ -1617,6 +1618,7 @@ func (q *Queries) ListStepRunEventsByWorkflowRunId(ctx context.Context, db DBTX,
|
||||
&i.Message,
|
||||
&i.Count,
|
||||
&i.Data,
|
||||
&i.WorkflowRunId,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1729,6 +1731,16 @@ deleted_sqis AS (
|
||||
sqi."stepRunId" = srs."id"
|
||||
AND sqi."workerId" = srs."workerId"
|
||||
),
|
||||
deleted_tqis AS (
|
||||
DELETE FROM
|
||||
"TimeoutQueueItem" tqi
|
||||
-- delete when step run id AND retry count tuples match
|
||||
USING
|
||||
step_runs_to_reassign srs
|
||||
WHERE
|
||||
tqi."stepRunId" = srs."id"
|
||||
AND tqi."retryCount" = srs."retryCount"
|
||||
),
|
||||
inserted_queue_items AS (
|
||||
INSERT INTO "QueueItem" (
|
||||
"stepRunId",
|
||||
@@ -2425,7 +2437,6 @@ const updateStepRunUnsetWorkerId = `-- name: UpdateStepRunUnsetWorkerId :one
|
||||
WITH oldsr AS (
|
||||
SELECT
|
||||
"id",
|
||||
"workerId",
|
||||
"retryCount"
|
||||
FROM
|
||||
"StepRun"
|
||||
|
||||
@@ -294,7 +294,31 @@ WHERE
|
||||
RETURNING
|
||||
"WorkflowRun".*;
|
||||
|
||||
-- name: UpdateWorkflowRunGroupKey :one
|
||||
-- name: UpdateWorkflowRunGroupKeyFromExpr :one
|
||||
UPDATE "WorkflowRun" wr
|
||||
SET "error" = CASE
|
||||
-- Final states are final, cannot be updated. We also can't move out of a queued state
|
||||
WHEN "status" IN ('SUCCEEDED', 'FAILED', 'QUEUED') THEN "error"
|
||||
WHEN sqlc.narg('error')::text IS NOT NULL THEN sqlc.narg('error')::text
|
||||
ELSE "error"
|
||||
END,
|
||||
"status" = CASE
|
||||
-- Final states are final, cannot be updated. We also can't move out of a queued state
|
||||
WHEN "status" IN ('SUCCEEDED', 'FAILED', 'QUEUED') THEN "status"
|
||||
-- When the concurrency expression errored, then the workflow is failed
|
||||
WHEN sqlc.narg('error')::text IS NOT NULL THEN 'FAILED'
|
||||
-- When the expression evaluated successfully, then queue the workflow run
|
||||
ELSE 'QUEUED'
|
||||
END,
|
||||
"concurrencyGroupId" = CASE
|
||||
WHEN sqlc.narg('concurrencyGroupId')::text IS NOT NULL THEN sqlc.narg('concurrencyGroupId')::text
|
||||
ELSE "concurrencyGroupId"
|
||||
END
|
||||
WHERE
|
||||
wr."id" = @workflowRunId::uuid
|
||||
RETURNING wr."id";
|
||||
|
||||
-- name: UpdateWorkflowRunGroupKeyFromRun :one
|
||||
WITH groupKeyRun AS (
|
||||
SELECT "id", "status" as groupKeyRunStatus, "output", "workflowRunId"
|
||||
FROM "GetGroupKeyRun" as groupKeyRun
|
||||
@@ -739,6 +763,7 @@ SELECT
|
||||
-- waiting on https://github.com/sqlc-dev/sqlc/pull/2858 for nullable fields
|
||||
wc."limitStrategy" as "concurrencyLimitStrategy",
|
||||
wc."maxRuns" as "concurrencyMaxRuns",
|
||||
wc."concurrencyGroupExpression" as "concurrencyGroupExpression",
|
||||
groupKeyRun."id" as "getGroupKeyRunId"
|
||||
FROM
|
||||
"WorkflowRun" as runs
|
||||
@@ -986,3 +1011,70 @@ WHERE
|
||||
AND sr."tenantId" = @tenantId::uuid
|
||||
AND sr."deletedAt" IS NULL
|
||||
ORDER BY sr."order" DESC;
|
||||
|
||||
-- name: BulkCreateWorkflowRunEvent :exec
|
||||
WITH input_values AS (
|
||||
SELECT
|
||||
unnest(@timeSeen::timestamp[]) AS "timeFirstSeen",
|
||||
unnest(@timeSeen::timestamp[]) AS "timeLastSeen",
|
||||
unnest(@workflowRunIds::uuid[]) AS "workflowRunId",
|
||||
unnest(cast(@reasons::text[] as"StepRunEventReason"[])) AS "reason",
|
||||
unnest(cast(@severities::text[] as "StepRunEventSeverity"[])) AS "severity",
|
||||
unnest(@messages::text[]) AS "message",
|
||||
1 AS "count",
|
||||
unnest(@data::jsonb[]) AS "data"
|
||||
),
|
||||
updated AS (
|
||||
UPDATE "StepRunEvent"
|
||||
SET
|
||||
"timeLastSeen" = input_values."timeLastSeen",
|
||||
"message" = input_values."message",
|
||||
"count" = "StepRunEvent"."count" + 1,
|
||||
"data" = input_values."data"
|
||||
FROM input_values
|
||||
WHERE
|
||||
"StepRunEvent"."workflowRunId" = input_values."workflowRunId"
|
||||
AND "StepRunEvent"."reason" = input_values."reason"
|
||||
AND "StepRunEvent"."severity" = input_values."severity"
|
||||
AND "StepRunEvent"."id" = (
|
||||
SELECT "id"
|
||||
FROM "StepRunEvent"
|
||||
WHERE "workflowRunId" = input_values."workflowRunId"
|
||||
ORDER BY "id" DESC
|
||||
LIMIT 1
|
||||
)
|
||||
RETURNING "StepRunEvent".*
|
||||
)
|
||||
INSERT INTO "StepRunEvent" (
|
||||
"timeFirstSeen",
|
||||
"timeLastSeen",
|
||||
"workflowRunId",
|
||||
"reason",
|
||||
"severity",
|
||||
"message",
|
||||
"count",
|
||||
"data"
|
||||
)
|
||||
SELECT
|
||||
"timeFirstSeen",
|
||||
"timeLastSeen",
|
||||
"workflowRunId",
|
||||
"reason",
|
||||
"severity",
|
||||
"message",
|
||||
"count",
|
||||
"data"
|
||||
FROM input_values
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM updated WHERE "workflowRunId" = input_values."workflowRunId"
|
||||
);
|
||||
|
||||
-- name: ListWorkflowRunEventsByWorkflowRunId :many
|
||||
SELECT
|
||||
sre.*
|
||||
FROM
|
||||
"StepRunEvent" sre
|
||||
WHERE
|
||||
sre."workflowRunId" = @workflowRunId::uuid
|
||||
ORDER BY
|
||||
sre."id" DESC;
|
||||
|
||||
@@ -11,6 +11,85 @@ import (
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const bulkCreateWorkflowRunEvent = `-- name: BulkCreateWorkflowRunEvent :exec
|
||||
WITH input_values AS (
|
||||
SELECT
|
||||
unnest($1::timestamp[]) AS "timeFirstSeen",
|
||||
unnest($1::timestamp[]) AS "timeLastSeen",
|
||||
unnest($2::uuid[]) AS "workflowRunId",
|
||||
unnest(cast($3::text[] as"StepRunEventReason"[])) AS "reason",
|
||||
unnest(cast($4::text[] as "StepRunEventSeverity"[])) AS "severity",
|
||||
unnest($5::text[]) AS "message",
|
||||
1 AS "count",
|
||||
unnest($6::jsonb[]) AS "data"
|
||||
),
|
||||
updated AS (
|
||||
UPDATE "StepRunEvent"
|
||||
SET
|
||||
"timeLastSeen" = input_values."timeLastSeen",
|
||||
"message" = input_values."message",
|
||||
"count" = "StepRunEvent"."count" + 1,
|
||||
"data" = input_values."data"
|
||||
FROM input_values
|
||||
WHERE
|
||||
"StepRunEvent"."workflowRunId" = input_values."workflowRunId"
|
||||
AND "StepRunEvent"."reason" = input_values."reason"
|
||||
AND "StepRunEvent"."severity" = input_values."severity"
|
||||
AND "StepRunEvent"."id" = (
|
||||
SELECT "id"
|
||||
FROM "StepRunEvent"
|
||||
WHERE "workflowRunId" = input_values."workflowRunId"
|
||||
ORDER BY "id" DESC
|
||||
LIMIT 1
|
||||
)
|
||||
RETURNING "StepRunEvent".id, "StepRunEvent"."timeFirstSeen", "StepRunEvent"."timeLastSeen", "StepRunEvent"."stepRunId", "StepRunEvent".reason, "StepRunEvent".severity, "StepRunEvent".message, "StepRunEvent".count, "StepRunEvent".data, "StepRunEvent"."workflowRunId"
|
||||
)
|
||||
INSERT INTO "StepRunEvent" (
|
||||
"timeFirstSeen",
|
||||
"timeLastSeen",
|
||||
"workflowRunId",
|
||||
"reason",
|
||||
"severity",
|
||||
"message",
|
||||
"count",
|
||||
"data"
|
||||
)
|
||||
SELECT
|
||||
"timeFirstSeen",
|
||||
"timeLastSeen",
|
||||
"workflowRunId",
|
||||
"reason",
|
||||
"severity",
|
||||
"message",
|
||||
"count",
|
||||
"data"
|
||||
FROM input_values
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM updated WHERE "workflowRunId" = input_values."workflowRunId"
|
||||
)
|
||||
`
|
||||
|
||||
type BulkCreateWorkflowRunEventParams struct {
|
||||
Timeseen []pgtype.Timestamp `json:"timeseen"`
|
||||
Workflowrunids []pgtype.UUID `json:"workflowrunids"`
|
||||
Reasons []string `json:"reasons"`
|
||||
Severities []string `json:"severities"`
|
||||
Messages []string `json:"messages"`
|
||||
Data [][]byte `json:"data"`
|
||||
}
|
||||
|
||||
func (q *Queries) BulkCreateWorkflowRunEvent(ctx context.Context, db DBTX, arg BulkCreateWorkflowRunEventParams) error {
|
||||
_, err := db.Exec(ctx, bulkCreateWorkflowRunEvent,
|
||||
arg.Timeseen,
|
||||
arg.Workflowrunids,
|
||||
arg.Reasons,
|
||||
arg.Severities,
|
||||
arg.Messages,
|
||||
arg.Data,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const countWorkflowRuns = `-- name: CountWorkflowRuns :one
|
||||
WITH runs AS (
|
||||
SELECT runs."id", runs."createdAt"
|
||||
@@ -889,6 +968,7 @@ SELECT
|
||||
-- waiting on https://github.com/sqlc-dev/sqlc/pull/2858 for nullable fields
|
||||
wc."limitStrategy" as "concurrencyLimitStrategy",
|
||||
wc."maxRuns" as "concurrencyMaxRuns",
|
||||
wc."concurrencyGroupExpression" as "concurrencyGroupExpression",
|
||||
groupKeyRun."id" as "getGroupKeyRunId"
|
||||
FROM
|
||||
"WorkflowRun" as runs
|
||||
@@ -916,13 +996,14 @@ type GetWorkflowRunParams struct {
|
||||
}
|
||||
|
||||
type GetWorkflowRunRow struct {
|
||||
WorkflowRun WorkflowRun `json:"workflow_run"`
|
||||
WorkflowRunTriggeredBy WorkflowRunTriggeredBy `json:"workflow_run_triggered_by"`
|
||||
WorkflowVersion WorkflowVersion `json:"workflow_version"`
|
||||
WorkflowName pgtype.Text `json:"workflowName"`
|
||||
ConcurrencyLimitStrategy NullConcurrencyLimitStrategy `json:"concurrencyLimitStrategy"`
|
||||
ConcurrencyMaxRuns pgtype.Int4 `json:"concurrencyMaxRuns"`
|
||||
GetGroupKeyRunId pgtype.UUID `json:"getGroupKeyRunId"`
|
||||
WorkflowRun WorkflowRun `json:"workflow_run"`
|
||||
WorkflowRunTriggeredBy WorkflowRunTriggeredBy `json:"workflow_run_triggered_by"`
|
||||
WorkflowVersion WorkflowVersion `json:"workflow_version"`
|
||||
WorkflowName pgtype.Text `json:"workflowName"`
|
||||
ConcurrencyLimitStrategy NullConcurrencyLimitStrategy `json:"concurrencyLimitStrategy"`
|
||||
ConcurrencyMaxRuns pgtype.Int4 `json:"concurrencyMaxRuns"`
|
||||
ConcurrencyGroupExpression pgtype.Text `json:"concurrencyGroupExpression"`
|
||||
GetGroupKeyRunId pgtype.UUID `json:"getGroupKeyRunId"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetWorkflowRun(ctx context.Context, db DBTX, arg GetWorkflowRunParams) ([]*GetWorkflowRunRow, error) {
|
||||
@@ -981,6 +1062,7 @@ func (q *Queries) GetWorkflowRun(ctx context.Context, db DBTX, arg GetWorkflowRu
|
||||
&i.WorkflowName,
|
||||
&i.ConcurrencyLimitStrategy,
|
||||
&i.ConcurrencyMaxRuns,
|
||||
&i.ConcurrencyGroupExpression,
|
||||
&i.GetGroupKeyRunId,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -1367,6 +1449,48 @@ func (q *Queries) ListStepsForJob(ctx context.Context, db DBTX, jobrunid pgtype.
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listWorkflowRunEventsByWorkflowRunId = `-- name: ListWorkflowRunEventsByWorkflowRunId :many
|
||||
SELECT
|
||||
sre.id, sre."timeFirstSeen", sre."timeLastSeen", sre."stepRunId", sre.reason, sre.severity, sre.message, sre.count, sre.data, sre."workflowRunId"
|
||||
FROM
|
||||
"StepRunEvent" sre
|
||||
WHERE
|
||||
sre."workflowRunId" = $1::uuid
|
||||
ORDER BY
|
||||
sre."id" DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListWorkflowRunEventsByWorkflowRunId(ctx context.Context, db DBTX, workflowrunid pgtype.UUID) ([]*StepRunEvent, error) {
|
||||
rows, err := db.Query(ctx, listWorkflowRunEventsByWorkflowRunId, workflowrunid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []*StepRunEvent
|
||||
for rows.Next() {
|
||||
var i StepRunEvent
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.TimeFirstSeen,
|
||||
&i.TimeLastSeen,
|
||||
&i.StepRunId,
|
||||
&i.Reason,
|
||||
&i.Severity,
|
||||
&i.Message,
|
||||
&i.Count,
|
||||
&i.Data,
|
||||
&i.WorkflowRunId,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, &i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listWorkflowRuns = `-- name: ListWorkflowRuns :many
|
||||
SELECT
|
||||
runs."createdAt", runs."updatedAt", runs."deletedAt", runs."tenantId", runs."workflowVersionId", runs.status, runs.error, runs."startedAt", runs."finishedAt", runs."concurrencyGroupId", runs."displayName", runs.id, runs."childIndex", runs."childKey", runs."parentId", runs."parentStepRunId", runs."additionalMetadata", runs.duration, runs.priority,
|
||||
@@ -2070,7 +2194,45 @@ func (q *Queries) UpdateWorkflowRun(ctx context.Context, db DBTX, arg UpdateWork
|
||||
return &i, err
|
||||
}
|
||||
|
||||
const updateWorkflowRunGroupKey = `-- name: UpdateWorkflowRunGroupKey :one
|
||||
const updateWorkflowRunGroupKeyFromExpr = `-- name: UpdateWorkflowRunGroupKeyFromExpr :one
|
||||
UPDATE "WorkflowRun" wr
|
||||
SET "error" = CASE
|
||||
-- Final states are final, cannot be updated. We also can't move out of a queued state
|
||||
WHEN "status" IN ('SUCCEEDED', 'FAILED', 'QUEUED') THEN "error"
|
||||
WHEN $1::text IS NOT NULL THEN $1::text
|
||||
ELSE "error"
|
||||
END,
|
||||
"status" = CASE
|
||||
-- Final states are final, cannot be updated. We also can't move out of a queued state
|
||||
WHEN "status" IN ('SUCCEEDED', 'FAILED', 'QUEUED') THEN "status"
|
||||
-- When the concurrency expression errored, then the workflow is failed
|
||||
WHEN $1::text IS NOT NULL THEN 'FAILED'
|
||||
-- When the expression evaluated successfully, then queue the workflow run
|
||||
ELSE 'QUEUED'
|
||||
END,
|
||||
"concurrencyGroupId" = CASE
|
||||
WHEN $2::text IS NOT NULL THEN $2::text
|
||||
ELSE "concurrencyGroupId"
|
||||
END
|
||||
WHERE
|
||||
wr."id" = $3::uuid
|
||||
RETURNING wr."id"
|
||||
`
|
||||
|
||||
type UpdateWorkflowRunGroupKeyFromExprParams struct {
|
||||
Error pgtype.Text `json:"error"`
|
||||
ConcurrencyGroupId pgtype.Text `json:"concurrencyGroupId"`
|
||||
Workflowrunid pgtype.UUID `json:"workflowrunid"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateWorkflowRunGroupKeyFromExpr(ctx context.Context, db DBTX, arg UpdateWorkflowRunGroupKeyFromExprParams) (pgtype.UUID, error) {
|
||||
row := db.QueryRow(ctx, updateWorkflowRunGroupKeyFromExpr, arg.Error, arg.ConcurrencyGroupId, arg.Workflowrunid)
|
||||
var id pgtype.UUID
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
const updateWorkflowRunGroupKeyFromRun = `-- name: UpdateWorkflowRunGroupKeyFromRun :one
|
||||
WITH groupKeyRun AS (
|
||||
SELECT "id", "status" as groupKeyRunStatus, "output", "workflowRunId"
|
||||
FROM "GetGroupKeyRun" as groupKeyRun
|
||||
@@ -2111,13 +2273,13 @@ workflowRun."tenantId" = $1::uuid
|
||||
RETURNING workflowrun."createdAt", workflowrun."updatedAt", workflowrun."deletedAt", workflowrun."tenantId", workflowrun."workflowVersionId", workflowrun.status, workflowrun.error, workflowrun."startedAt", workflowrun."finishedAt", workflowrun."concurrencyGroupId", workflowrun."displayName", workflowrun.id, workflowrun."childIndex", workflowrun."childKey", workflowrun."parentId", workflowrun."parentStepRunId", workflowrun."additionalMetadata", workflowrun.duration, workflowrun.priority
|
||||
`
|
||||
|
||||
type UpdateWorkflowRunGroupKeyParams struct {
|
||||
type UpdateWorkflowRunGroupKeyFromRunParams struct {
|
||||
Tenantid pgtype.UUID `json:"tenantid"`
|
||||
Groupkeyrunid pgtype.UUID `json:"groupkeyrunid"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateWorkflowRunGroupKey(ctx context.Context, db DBTX, arg UpdateWorkflowRunGroupKeyParams) (*WorkflowRun, error) {
|
||||
row := db.QueryRow(ctx, updateWorkflowRunGroupKey, arg.Tenantid, arg.Groupkeyrunid)
|
||||
func (q *Queries) UpdateWorkflowRunGroupKeyFromRun(ctx context.Context, db DBTX, arg UpdateWorkflowRunGroupKeyFromRunParams) (*WorkflowRun, error) {
|
||||
row := db.QueryRow(ctx, updateWorkflowRunGroupKeyFromRun, arg.Tenantid, arg.Groupkeyrunid)
|
||||
var i WorkflowRun
|
||||
err := row.Scan(
|
||||
&i.CreatedAt,
|
||||
|
||||
@@ -146,15 +146,17 @@ INSERT INTO "WorkflowConcurrency" (
|
||||
"workflowVersionId",
|
||||
"getConcurrencyGroupId",
|
||||
"maxRuns",
|
||||
"limitStrategy"
|
||||
"limitStrategy",
|
||||
"concurrencyGroupExpression"
|
||||
) VALUES (
|
||||
@id::uuid,
|
||||
gen_random_uuid(),
|
||||
coalesce(sqlc.narg('createdAt')::timestamp, CURRENT_TIMESTAMP),
|
||||
coalesce(sqlc.narg('updatedAt')::timestamp, CURRENT_TIMESTAMP),
|
||||
@workflowVersionId::uuid,
|
||||
@getConcurrencyGroupId::uuid,
|
||||
sqlc.narg('getConcurrencyGroupId')::uuid,
|
||||
coalesce(sqlc.narg('maxRuns')::integer, 1),
|
||||
coalesce(sqlc.narg('limitStrategy')::"ConcurrencyLimitStrategy", 'CANCEL_IN_PROGRESS')
|
||||
coalesce(sqlc.narg('limitStrategy')::"ConcurrencyLimitStrategy", 'CANCEL_IN_PROGRESS'),
|
||||
sqlc.narg('concurrencyGroupExpression')::text
|
||||
) RETURNING *;
|
||||
|
||||
-- name: CreateJob :one
|
||||
@@ -364,7 +366,9 @@ SELECT
|
||||
sqlc.embed(workflowVersions),
|
||||
w."name" as "workflowName",
|
||||
wc."limitStrategy" as "concurrencyLimitStrategy",
|
||||
wc."maxRuns" as "concurrencyMaxRuns"
|
||||
wc."maxRuns" as "concurrencyMaxRuns",
|
||||
wc."getConcurrencyGroupId" as "concurrencyGroupId",
|
||||
wc."concurrencyGroupExpression" as "concurrencyGroupExpression"
|
||||
FROM
|
||||
"WorkflowVersion" as workflowVersions
|
||||
JOIN
|
||||
|
||||
@@ -464,37 +464,39 @@ INSERT INTO "WorkflowConcurrency" (
|
||||
"workflowVersionId",
|
||||
"getConcurrencyGroupId",
|
||||
"maxRuns",
|
||||
"limitStrategy"
|
||||
"limitStrategy",
|
||||
"concurrencyGroupExpression"
|
||||
) VALUES (
|
||||
$1::uuid,
|
||||
gen_random_uuid(),
|
||||
coalesce($1::timestamp, CURRENT_TIMESTAMP),
|
||||
coalesce($2::timestamp, CURRENT_TIMESTAMP),
|
||||
coalesce($3::timestamp, CURRENT_TIMESTAMP),
|
||||
$3::uuid,
|
||||
$4::uuid,
|
||||
$5::uuid,
|
||||
coalesce($6::integer, 1),
|
||||
coalesce($7::"ConcurrencyLimitStrategy", 'CANCEL_IN_PROGRESS')
|
||||
) RETURNING id, "createdAt", "updatedAt", "workflowVersionId", "getConcurrencyGroupId", "maxRuns", "limitStrategy"
|
||||
coalesce($5::integer, 1),
|
||||
coalesce($6::"ConcurrencyLimitStrategy", 'CANCEL_IN_PROGRESS'),
|
||||
$7::text
|
||||
) RETURNING id, "createdAt", "updatedAt", "workflowVersionId", "getConcurrencyGroupId", "maxRuns", "limitStrategy", "concurrencyGroupExpression"
|
||||
`
|
||||
|
||||
type CreateWorkflowConcurrencyParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
CreatedAt pgtype.Timestamp `json:"createdAt"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updatedAt"`
|
||||
Workflowversionid pgtype.UUID `json:"workflowversionid"`
|
||||
Getconcurrencygroupid pgtype.UUID `json:"getconcurrencygroupid"`
|
||||
MaxRuns pgtype.Int4 `json:"maxRuns"`
|
||||
LimitStrategy NullConcurrencyLimitStrategy `json:"limitStrategy"`
|
||||
CreatedAt pgtype.Timestamp `json:"createdAt"`
|
||||
UpdatedAt pgtype.Timestamp `json:"updatedAt"`
|
||||
Workflowversionid pgtype.UUID `json:"workflowversionid"`
|
||||
GetConcurrencyGroupId pgtype.UUID `json:"getConcurrencyGroupId"`
|
||||
MaxRuns pgtype.Int4 `json:"maxRuns"`
|
||||
LimitStrategy NullConcurrencyLimitStrategy `json:"limitStrategy"`
|
||||
ConcurrencyGroupExpression pgtype.Text `json:"concurrencyGroupExpression"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateWorkflowConcurrency(ctx context.Context, db DBTX, arg CreateWorkflowConcurrencyParams) (*WorkflowConcurrency, error) {
|
||||
row := db.QueryRow(ctx, createWorkflowConcurrency,
|
||||
arg.ID,
|
||||
arg.CreatedAt,
|
||||
arg.UpdatedAt,
|
||||
arg.Workflowversionid,
|
||||
arg.Getconcurrencygroupid,
|
||||
arg.GetConcurrencyGroupId,
|
||||
arg.MaxRuns,
|
||||
arg.LimitStrategy,
|
||||
arg.ConcurrencyGroupExpression,
|
||||
)
|
||||
var i WorkflowConcurrency
|
||||
err := row.Scan(
|
||||
@@ -505,6 +507,7 @@ func (q *Queries) CreateWorkflowConcurrency(ctx context.Context, db DBTX, arg Cr
|
||||
&i.GetConcurrencyGroupId,
|
||||
&i.MaxRuns,
|
||||
&i.LimitStrategy,
|
||||
&i.ConcurrencyGroupExpression,
|
||||
)
|
||||
return &i, err
|
||||
}
|
||||
@@ -930,7 +933,9 @@ SELECT
|
||||
workflowversions.id, workflowversions."createdAt", workflowversions."updatedAt", workflowversions."deletedAt", workflowversions.version, workflowversions."order", workflowversions."workflowId", workflowversions.checksum, workflowversions."scheduleTimeout", workflowversions."onFailureJobId", workflowversions.sticky, workflowversions.kind, workflowversions."defaultPriority",
|
||||
w."name" as "workflowName",
|
||||
wc."limitStrategy" as "concurrencyLimitStrategy",
|
||||
wc."maxRuns" as "concurrencyMaxRuns"
|
||||
wc."maxRuns" as "concurrencyMaxRuns",
|
||||
wc."getConcurrencyGroupId" as "concurrencyGroupId",
|
||||
wc."concurrencyGroupExpression" as "concurrencyGroupExpression"
|
||||
FROM
|
||||
"WorkflowVersion" as workflowVersions
|
||||
JOIN
|
||||
@@ -950,10 +955,12 @@ type GetWorkflowVersionForEngineParams struct {
|
||||
}
|
||||
|
||||
type GetWorkflowVersionForEngineRow struct {
|
||||
WorkflowVersion WorkflowVersion `json:"workflow_version"`
|
||||
WorkflowName string `json:"workflowName"`
|
||||
ConcurrencyLimitStrategy NullConcurrencyLimitStrategy `json:"concurrencyLimitStrategy"`
|
||||
ConcurrencyMaxRuns pgtype.Int4 `json:"concurrencyMaxRuns"`
|
||||
WorkflowVersion WorkflowVersion `json:"workflow_version"`
|
||||
WorkflowName string `json:"workflowName"`
|
||||
ConcurrencyLimitStrategy NullConcurrencyLimitStrategy `json:"concurrencyLimitStrategy"`
|
||||
ConcurrencyMaxRuns pgtype.Int4 `json:"concurrencyMaxRuns"`
|
||||
ConcurrencyGroupId pgtype.UUID `json:"concurrencyGroupId"`
|
||||
ConcurrencyGroupExpression pgtype.Text `json:"concurrencyGroupExpression"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetWorkflowVersionForEngine(ctx context.Context, db DBTX, arg GetWorkflowVersionForEngineParams) ([]*GetWorkflowVersionForEngineRow, error) {
|
||||
@@ -982,6 +989,8 @@ func (q *Queries) GetWorkflowVersionForEngine(ctx context.Context, db DBTX, arg
|
||||
&i.WorkflowName,
|
||||
&i.ConcurrencyLimitStrategy,
|
||||
&i.ConcurrencyMaxRuns,
|
||||
&i.ConcurrencyGroupId,
|
||||
&i.ConcurrencyGroupExpression,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ func (s *getGroupKeyRunRepository) UpdateGetGroupKeyRun(ctx context.Context, ten
|
||||
Tenantid: pgTenantId,
|
||||
}
|
||||
|
||||
updateWorkflowRunParams := dbsqlc.UpdateWorkflowRunGroupKeyParams{
|
||||
updateWorkflowRunParams := dbsqlc.UpdateWorkflowRunGroupKeyFromRunParams{
|
||||
Tenantid: pgTenantId,
|
||||
Groupkeyrunid: sqlchelpers.UUIDFromStr(getGroupKeyRunId),
|
||||
}
|
||||
@@ -174,7 +174,7 @@ func (s *getGroupKeyRunRepository) UpdateGetGroupKeyRun(ctx context.Context, ten
|
||||
|
||||
// only update workflow run if status or output has changed
|
||||
if opts.Status != nil || opts.Output != nil {
|
||||
_, err = s.queries.UpdateWorkflowRunGroupKey(ctx, tx, updateWorkflowRunParams)
|
||||
_, err = s.queries.UpdateWorkflowRunGroupKeyFromRun(ctx, tx, updateWorkflowRunParams)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not resolve workflow run status from get group key run: %w", err)
|
||||
|
||||
@@ -155,11 +155,21 @@ func (s *stepRunAPIRepository) ListStepRunEventsByWorkflowRunId(ctx context.Cont
|
||||
}
|
||||
}
|
||||
|
||||
events, err := s.queries.ListStepRunEventsByWorkflowRunId(context.Background(), tx, listParams)
|
||||
allEvents, err := s.queries.ListWorkflowRunEventsByWorkflowRunId(ctx, tx, sqlchelpers.UUIDFromStr(workflowRunId))
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
events = make([]*dbsqlc.StepRunEvent, 0)
|
||||
allEvents = make([]*dbsqlc.StepRunEvent, 0)
|
||||
} else {
|
||||
return nil, fmt.Errorf("could not list workflow run events: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
srEvents, err := s.queries.ListStepRunEventsByWorkflowRunId(context.Background(), tx, listParams)
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
srEvents = make([]*dbsqlc.StepRunEvent, 0)
|
||||
} else {
|
||||
return nil, fmt.Errorf("could not list step run events: %w", err)
|
||||
}
|
||||
@@ -171,8 +181,15 @@ func (s *stepRunAPIRepository) ListStepRunEventsByWorkflowRunId(ctx context.Cont
|
||||
return nil, fmt.Errorf("could not commit transaction: %w", err)
|
||||
}
|
||||
|
||||
allEvents = append(allEvents, srEvents...)
|
||||
|
||||
// sort all events by id asc
|
||||
sort.Slice(allEvents, func(i, j int) bool {
|
||||
return allEvents[i].ID > allEvents[j].ID
|
||||
})
|
||||
|
||||
return &repository.ListStepRunEventResult{
|
||||
Rows: events,
|
||||
Rows: allEvents,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -412,7 +429,7 @@ func (s *stepRunEngineRepository) ListStepRunsToReassign(ctx context.Context, te
|
||||
data[i] = map[string]interface{}{"worker_id": workerId}
|
||||
}
|
||||
|
||||
deferredBulkStepRunEvents(
|
||||
bulkStepRunEvents(
|
||||
ctx,
|
||||
s.l,
|
||||
s.pool,
|
||||
@@ -629,6 +646,7 @@ func deferredStepRunEvent(
|
||||
}
|
||||
|
||||
func (s *stepRunEngineRepository) bulkStepRunsAssigned(
|
||||
assignedAt time.Time,
|
||||
stepRunIds []pgtype.UUID,
|
||||
workerIds []pgtype.UUID,
|
||||
) {
|
||||
@@ -651,7 +669,7 @@ func (s *stepRunEngineRepository) bulkStepRunsAssigned(
|
||||
|
||||
workerIdToStepRunIds[workerId] = append(workerIdToStepRunIds[workerId], sqlchelpers.UUIDToStr(stepRunIds[i]))
|
||||
messages[i] = fmt.Sprintf("Assigned to worker %s", workerId)
|
||||
timeSeen[i] = sqlchelpers.TimestampFromTime(time.Now().UTC())
|
||||
timeSeen[i] = sqlchelpers.TimestampFromTime(assignedAt)
|
||||
reasons[i] = dbsqlc.StepRunEventReasonASSIGNED
|
||||
severities[i] = dbsqlc.StepRunEventSeverityINFO
|
||||
data[i] = map[string]interface{}{"worker_id": workerId}
|
||||
@@ -675,7 +693,7 @@ func (s *stepRunEngineRepository) bulkStepRunsAssigned(
|
||||
s.l.Err(err).Msg("could not create worker assign events")
|
||||
}
|
||||
|
||||
deferredBulkStepRunEvents(
|
||||
bulkStepRunEvents(
|
||||
ctx,
|
||||
s.l,
|
||||
s.pool,
|
||||
@@ -710,7 +728,7 @@ func (s *stepRunEngineRepository) bulkStepRunsUnassigned(
|
||||
data[i] = map[string]interface{}{}
|
||||
}
|
||||
|
||||
deferredBulkStepRunEvents(
|
||||
bulkStepRunEvents(
|
||||
ctx,
|
||||
s.l,
|
||||
s.pool,
|
||||
@@ -745,7 +763,7 @@ func (s *stepRunEngineRepository) bulkStepRunsRateLimited(
|
||||
data[i] = map[string]interface{}{}
|
||||
}
|
||||
|
||||
deferredBulkStepRunEvents(
|
||||
bulkStepRunEvents(
|
||||
ctx,
|
||||
s.l,
|
||||
s.pool,
|
||||
@@ -759,7 +777,7 @@ func (s *stepRunEngineRepository) bulkStepRunsRateLimited(
|
||||
)
|
||||
}
|
||||
|
||||
func deferredBulkStepRunEvents(
|
||||
func bulkStepRunEvents(
|
||||
ctx context.Context,
|
||||
l *zerolog.Logger,
|
||||
dbtx dbsqlc.DBTX,
|
||||
@@ -1286,7 +1304,7 @@ func (s *stepRunEngineRepository) QueueStepRuns(ctx context.Context, qlp *zerolo
|
||||
return emptyRes, fmt.Errorf("could not commit transaction: %w", err)
|
||||
}
|
||||
|
||||
defer s.bulkStepRunsAssigned(plan.StepRunIds, plan.WorkerIds)
|
||||
defer s.bulkStepRunsAssigned(time.Now().UTC(), plan.StepRunIds, plan.WorkerIds)
|
||||
defer s.bulkStepRunsUnassigned(plan.UnassignedStepRunIds)
|
||||
defer s.bulkStepRunsRateLimited(plan.RateLimitedStepRuns)
|
||||
|
||||
@@ -1587,7 +1605,7 @@ func (s *stepRunEngineRepository) ProcessStepRunUpdates(ctx context.Context, qlp
|
||||
startRunEvents := time.Now()
|
||||
|
||||
// NOTE: actually not deferred
|
||||
deferredBulkStepRunEvents(ctx, s.l, tx, s.queries, eventStepRunIds, eventTimeSeen, eventReasons, eventSeverities, eventMessages, eventData)
|
||||
bulkStepRunEvents(ctx, s.l, tx, s.queries, eventStepRunIds, eventTimeSeen, eventReasons, eventSeverities, eventMessages, eventData)
|
||||
|
||||
durationRunEvents := time.Since(startRunEvents)
|
||||
|
||||
@@ -2269,6 +2287,18 @@ func (s *stepRunEngineRepository) QueueStepRun(ctx context.Context, tenantId, st
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if this is an internal retry, and the step run is in a running or final state, this is a no-op. The internal retry
|
||||
// may have be delayed (for example, timing out when sending the action to the worker), while the system
|
||||
// may have already reassigned the step run to another.
|
||||
if opts.IsInternalRetry && (repository.IsFinalStepRunStatus(innerStepRun.SRStatus) || innerStepRun.SRStatus == dbsqlc.StepRunStatusRUNNING) {
|
||||
return nil, repository.ErrAlreadyRunning
|
||||
}
|
||||
|
||||
// if this is not a retry, and the step run is already in a pending assignment state, this is a no-op
|
||||
if !opts.IsRetry && innerStepRun.SRStatus == dbsqlc.StepRunStatusPENDINGASSIGNMENT {
|
||||
return nil, repository.ErrAlreadyQueued
|
||||
}
|
||||
|
||||
err = s.queries.QueueStepRun(ctx, tx, queueParams)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -593,24 +593,30 @@ func (r *workflowEngineRepository) createWorkflowVersionTxs(ctx context.Context,
|
||||
|
||||
// create concurrency group
|
||||
if opts.Concurrency != nil {
|
||||
// upsert the action
|
||||
action, err := r.queries.UpsertAction(
|
||||
ctx,
|
||||
tx,
|
||||
dbsqlc.UpsertActionParams{
|
||||
Action: opts.Concurrency.Action,
|
||||
Tenantid: tenantId,
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not upsert action: %w", err)
|
||||
params := dbsqlc.CreateWorkflowConcurrencyParams{
|
||||
Workflowversionid: sqlcWorkflowVersion.ID,
|
||||
}
|
||||
|
||||
params := dbsqlc.CreateWorkflowConcurrencyParams{
|
||||
ID: sqlchelpers.UUIDFromStr(uuid.New().String()),
|
||||
Workflowversionid: sqlcWorkflowVersion.ID,
|
||||
Getconcurrencygroupid: action.ID,
|
||||
// upsert the action
|
||||
if opts.Concurrency.Action != nil {
|
||||
action, err := r.queries.UpsertAction(
|
||||
ctx,
|
||||
tx,
|
||||
dbsqlc.UpsertActionParams{
|
||||
Action: *opts.Concurrency.Action,
|
||||
Tenantid: tenantId,
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not upsert action: %w", err)
|
||||
}
|
||||
|
||||
params.GetConcurrencyGroupId = action.ID
|
||||
}
|
||||
|
||||
if opts.Concurrency.Expression != nil {
|
||||
params.ConcurrencyGroupExpression = sqlchelpers.TextFromStr(*opts.Concurrency.Expression)
|
||||
}
|
||||
|
||||
if opts.Concurrency.MaxRuns != nil {
|
||||
|
||||
@@ -73,7 +73,7 @@ func (w *workflowRunAPIRepository) WorkflowRunMetricsCount(ctx context.Context,
|
||||
return workflowRunMetricsCount(context.Background(), w.pool, w.queries, tenantId, opts)
|
||||
}
|
||||
|
||||
func (w *workflowRunAPIRepository) GetWorkflowRunInputData(tenantId, workflowRunId string) (map[string]interface{}, error) {
|
||||
func (w *workflowRunEngineRepository) GetWorkflowRunInputData(tenantId, workflowRunId string) (map[string]interface{}, error) {
|
||||
lookupData := datautils.JobRunLookupData{}
|
||||
|
||||
jsonBytes, err := w.queries.GetWorkflowRunInput(
|
||||
@@ -107,16 +107,6 @@ func (w *workflowRunAPIRepository) CreateNewWorkflowRun(ctx context.Context, ten
|
||||
|
||||
id := sqlchelpers.UUIDToStr(workflowRun.ID)
|
||||
|
||||
// res, err := w.client.WorkflowRun.FindUnique(
|
||||
// db.WorkflowRun.ID.Equals(id),
|
||||
// ).With(
|
||||
// defaultWorkflowRunPopulator()...,
|
||||
// ).Exec(context.Background())
|
||||
|
||||
// if err != nil {
|
||||
// return nil, nil, err
|
||||
// }
|
||||
|
||||
for _, cb := range w.callbacks {
|
||||
cb.Do(workflowRun) // nolint: errcheck
|
||||
}
|
||||
@@ -125,6 +115,119 @@ func (w *workflowRunAPIRepository) CreateNewWorkflowRun(ctx context.Context, ten
|
||||
})
|
||||
}
|
||||
|
||||
type updateWorkflowRunQueueData struct {
|
||||
WorkflowRunId string `json:"workflow_run_id"`
|
||||
|
||||
Event *repository.CreateStepRunEventOpts `json:"event,omitempty"`
|
||||
}
|
||||
|
||||
func (w *workflowRunEngineRepository) ProcessWorkflowRunUpdates(ctx context.Context, tenantId string) (bool, error) {
|
||||
ctx, span := telemetry.NewSpan(ctx, "process-workflow-run-updates-database")
|
||||
defer span.End()
|
||||
|
||||
pgTenantId := sqlchelpers.UUIDFromStr(tenantId)
|
||||
|
||||
limit := 100
|
||||
|
||||
tx, commit, rollback, err := prepareTx(ctx, w.pool, w.l, 25000)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
defer rollback()
|
||||
|
||||
// list queues
|
||||
queueItems, err := w.queries.ListInternalQueueItems(ctx, tx, dbsqlc.ListInternalQueueItemsParams{
|
||||
Tenantid: pgTenantId,
|
||||
Queue: dbsqlc.InternalQueueWORKFLOWRUNUPDATE,
|
||||
Limit: pgtype.Int4{
|
||||
Int32: int32(limit),
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("could not list internal queue items: %w", err)
|
||||
}
|
||||
|
||||
data, err := toQueueItemData[updateWorkflowRunQueueData](queueItems)
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("could not convert internal queue item data to worker semaphore queue data: %w", err)
|
||||
}
|
||||
|
||||
eventTimeSeen := make([]pgtype.Timestamp, 0, len(data))
|
||||
eventReasons := make([]dbsqlc.StepRunEventReason, 0, len(data))
|
||||
eventWorkflowRunIds := make([]pgtype.UUID, 0, len(data))
|
||||
eventSeverities := make([]dbsqlc.StepRunEventSeverity, 0, len(data))
|
||||
eventMessages := make([]string, 0, len(data))
|
||||
eventData := make([]map[string]interface{}, 0, len(data))
|
||||
dedupe := make(map[string]bool)
|
||||
|
||||
for _, item := range data {
|
||||
workflowRunId := sqlchelpers.UUIDFromStr(item.WorkflowRunId)
|
||||
|
||||
if item.Event.EventMessage == nil || item.Event.EventReason == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
dedupeKey := fmt.Sprintf("EVENT-%s-%s", item.WorkflowRunId, *item.Event.EventReason)
|
||||
|
||||
if _, ok := dedupe[dedupeKey]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
dedupe[dedupeKey] = true
|
||||
|
||||
eventWorkflowRunIds = append(eventWorkflowRunIds, workflowRunId)
|
||||
eventMessages = append(eventMessages, *item.Event.EventMessage)
|
||||
eventReasons = append(eventReasons, *item.Event.EventReason)
|
||||
|
||||
if item.Event.EventSeverity != nil {
|
||||
eventSeverities = append(eventSeverities, *item.Event.EventSeverity)
|
||||
} else {
|
||||
eventSeverities = append(eventSeverities, dbsqlc.StepRunEventSeverityINFO)
|
||||
}
|
||||
|
||||
if item.Event.EventData != nil {
|
||||
eventData = append(eventData, item.Event.EventData)
|
||||
} else {
|
||||
eventData = append(eventData, map[string]interface{}{})
|
||||
}
|
||||
|
||||
if item.Event.Timestamp != nil {
|
||||
eventTimeSeen = append(eventTimeSeen, sqlchelpers.TimestampFromTime(*item.Event.Timestamp))
|
||||
} else {
|
||||
eventTimeSeen = append(eventTimeSeen, sqlchelpers.TimestampFromTime(time.Now().UTC()))
|
||||
}
|
||||
}
|
||||
|
||||
qiIds := make([]int64, 0, len(data))
|
||||
|
||||
for _, item := range queueItems {
|
||||
qiIds = append(qiIds, item.ID)
|
||||
}
|
||||
|
||||
// update the processed semaphore queue items
|
||||
err = w.queries.MarkInternalQueueItemsProcessed(ctx, tx, qiIds)
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("could not mark worker semaphore queue items processed: %w", err)
|
||||
}
|
||||
|
||||
// NOTE: actually not deferred
|
||||
bulkWorkflowRunEvents(ctx, w.l, tx, w.queries, eventWorkflowRunIds, eventTimeSeen, eventReasons, eventSeverities, eventMessages, eventData)
|
||||
|
||||
err = commit(ctx)
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("could not commit transaction: %w", err)
|
||||
}
|
||||
|
||||
return len(queueItems) == limit, nil
|
||||
}
|
||||
|
||||
func (w *workflowRunAPIRepository) GetWorkflowRunById(ctx context.Context, tenantId, id string) (*dbsqlc.GetWorkflowRunByIdRow, error) {
|
||||
return w.queries.GetWorkflowRunById(ctx, w.pool, dbsqlc.GetWorkflowRunByIdParams{
|
||||
Tenantid: sqlchelpers.UUIDFromStr(tenantId),
|
||||
@@ -494,6 +597,61 @@ func (s *workflowRunEngineRepository) ReplayWorkflowRun(ctx context.Context, ten
|
||||
return workflowRuns[0], nil
|
||||
}
|
||||
|
||||
func (s *workflowRunEngineRepository) UpdateWorkflowRunFromGroupKeyEval(ctx context.Context, tenantId, workflowRunId string, opts *repository.UpdateWorkflowRunFromGroupKeyEvalOpts) error {
|
||||
if err := s.v.Validate(opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pgWorkflowRunId := sqlchelpers.UUIDFromStr(workflowRunId)
|
||||
|
||||
updateParams := dbsqlc.UpdateWorkflowRunGroupKeyFromExprParams{
|
||||
Workflowrunid: pgWorkflowRunId,
|
||||
}
|
||||
|
||||
eventParams := repository.CreateStepRunEventOpts{}
|
||||
|
||||
if opts.GroupKey != nil {
|
||||
updateParams.ConcurrencyGroupId = sqlchelpers.TextFromStr(*opts.GroupKey)
|
||||
|
||||
now := time.Now().UTC()
|
||||
|
||||
eventParams.EventReason = repository.StepRunEventReasonPtr(dbsqlc.StepRunEventReasonWORKFLOWRUNGROUPKEYSUCCEEDED)
|
||||
eventParams.EventSeverity = repository.StepRunEventSeverityPtr(dbsqlc.StepRunEventSeverityINFO)
|
||||
eventParams.EventMessage = repository.StringPtr(fmt.Sprintf("Workflow run group key evaluated as %s", *opts.GroupKey))
|
||||
eventParams.Timestamp = &now
|
||||
}
|
||||
|
||||
if opts.Error != nil {
|
||||
updateParams.Error = sqlchelpers.TextFromStr(*opts.Error)
|
||||
|
||||
now := time.Now().UTC()
|
||||
|
||||
eventParams.EventReason = repository.StepRunEventReasonPtr(dbsqlc.StepRunEventReasonWORKFLOWRUNGROUPKEYFAILED)
|
||||
eventParams.EventSeverity = repository.StepRunEventSeverityPtr(dbsqlc.StepRunEventSeverityCRITICAL)
|
||||
eventParams.EventMessage = repository.StringPtr(fmt.Sprintf("Error evaluating workflow run group key: %s", *opts.Error))
|
||||
eventParams.Timestamp = &now
|
||||
}
|
||||
|
||||
_, err := s.queries.UpdateWorkflowRunGroupKeyFromExpr(ctx, s.pool, updateParams)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not update workflow run group key from expr: %w", err)
|
||||
}
|
||||
|
||||
defer insertWorkflowRunQueueItem( // nolint: errcheck
|
||||
ctx,
|
||||
s.pool,
|
||||
s.queries,
|
||||
tenantId,
|
||||
updateWorkflowRunQueueData{
|
||||
WorkflowRunId: workflowRunId,
|
||||
Event: &eventParams,
|
||||
},
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func listWorkflowRuns(ctx context.Context, pool *pgxpool.Pool, queries *dbsqlc.Queries, l *zerolog.Logger, tenantId string, opts *repository.ListWorkflowRunsOpts) (*repository.ListWorkflowRunsResult, error) {
|
||||
res := &repository.ListWorkflowRunsResult{}
|
||||
|
||||
@@ -1044,37 +1202,6 @@ func createNewWorkflowRun(ctx context.Context, pool *pgxpool.Pool, queries *dbsq
|
||||
return sqlcWorkflowRun, nil
|
||||
}
|
||||
|
||||
func defaultWorkflowRunPopulator() []db.WorkflowRunRelationWith {
|
||||
return []db.WorkflowRunRelationWith{
|
||||
db.WorkflowRun.WorkflowVersion.Fetch().With(
|
||||
db.WorkflowVersion.Workflow.Fetch(),
|
||||
db.WorkflowVersion.Concurrency.Fetch().With(
|
||||
db.WorkflowConcurrency.GetConcurrencyGroup.Fetch(),
|
||||
),
|
||||
),
|
||||
db.WorkflowRun.GetGroupKeyRun.Fetch(),
|
||||
db.WorkflowRun.TriggeredBy.Fetch().With(
|
||||
db.WorkflowRunTriggeredBy.Event.Fetch(),
|
||||
db.WorkflowRunTriggeredBy.Cron.Fetch(),
|
||||
),
|
||||
db.WorkflowRun.JobRuns.Fetch().With(
|
||||
db.JobRun.Job.Fetch().With(
|
||||
db.Job.Steps.Fetch().With(
|
||||
db.Step.Action.Fetch(),
|
||||
db.Step.Parents.Fetch(),
|
||||
),
|
||||
),
|
||||
db.JobRun.StepRuns.Fetch().With(
|
||||
db.StepRun.ChildWorkflowRuns.Fetch(),
|
||||
db.StepRun.Step.Fetch().With(
|
||||
db.Step.Action.Fetch(),
|
||||
db.Step.Parents.Fetch(),
|
||||
),
|
||||
),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func isUniqueViolationOnDedupe(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
@@ -1083,3 +1210,72 @@ func isUniqueViolationOnDedupe(err error) bool {
|
||||
return strings.Contains(err.Error(), "WorkflowRunDedupe_tenantId_workflowId_value_key") &&
|
||||
strings.Contains(err.Error(), "SQLSTATE 23505")
|
||||
}
|
||||
|
||||
func insertWorkflowRunQueueItem(
|
||||
ctx context.Context,
|
||||
dbtx dbsqlc.DBTX,
|
||||
queries *dbsqlc.Queries,
|
||||
tenantId string,
|
||||
data updateWorkflowRunQueueData,
|
||||
) error {
|
||||
insertData := make([]any, 1)
|
||||
insertData[0] = data
|
||||
|
||||
return bulkInsertInternalQueueItem(
|
||||
ctx,
|
||||
dbtx,
|
||||
queries,
|
||||
tenantId,
|
||||
dbsqlc.InternalQueueWORKFLOWRUNUPDATE,
|
||||
insertData,
|
||||
)
|
||||
}
|
||||
|
||||
func bulkWorkflowRunEvents(
|
||||
ctx context.Context,
|
||||
l *zerolog.Logger,
|
||||
dbtx dbsqlc.DBTX,
|
||||
queries *dbsqlc.Queries,
|
||||
workflowRunIds []pgtype.UUID,
|
||||
timeSeen []pgtype.Timestamp,
|
||||
reasons []dbsqlc.StepRunEventReason,
|
||||
severities []dbsqlc.StepRunEventSeverity,
|
||||
messages []string,
|
||||
data []map[string]interface{},
|
||||
) {
|
||||
inputData := [][]byte{}
|
||||
inputReasons := []string{}
|
||||
inputSeverities := []string{}
|
||||
|
||||
for _, d := range data {
|
||||
dataBytes, err := json.Marshal(d)
|
||||
|
||||
if err != nil {
|
||||
l.Err(err).Msg("could not marshal deferred step run event data")
|
||||
return
|
||||
}
|
||||
|
||||
inputData = append(inputData, dataBytes)
|
||||
}
|
||||
|
||||
for _, r := range reasons {
|
||||
inputReasons = append(inputReasons, string(r))
|
||||
}
|
||||
|
||||
for _, s := range severities {
|
||||
inputSeverities = append(inputSeverities, string(s))
|
||||
}
|
||||
|
||||
err := queries.BulkCreateWorkflowRunEvent(ctx, dbtx, dbsqlc.BulkCreateWorkflowRunEventParams{
|
||||
Workflowrunids: workflowRunIds,
|
||||
Reasons: inputReasons,
|
||||
Severities: inputSeverities,
|
||||
Messages: messages,
|
||||
Data: inputData,
|
||||
Timeseen: timeSeen,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
l.Err(err).Msg("could not create deferred step run event")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,10 +78,11 @@ func StepRunEventSeverityPtr(severity dbsqlc.StepRunEventSeverity) *dbsqlc.StepR
|
||||
return &severity
|
||||
}
|
||||
|
||||
var ErrStepRunIsNotPending = fmt.Errorf("step run is not pending")
|
||||
var ErrNoWorkerAvailable = fmt.Errorf("no worker available")
|
||||
var ErrRateLimitExceeded = fmt.Errorf("rate limit exceeded")
|
||||
var ErrStepRunIsNotAssigned = fmt.Errorf("step run is not assigned")
|
||||
var ErrAlreadyQueued = fmt.Errorf("step run is already queued")
|
||||
var ErrAlreadyRunning = fmt.Errorf("step run is already running")
|
||||
|
||||
type StepRunUpdateInfo struct {
|
||||
WorkflowRunFinalState bool
|
||||
|
||||
@@ -56,14 +56,17 @@ type CreateWorkflowVersionOpts struct {
|
||||
}
|
||||
|
||||
type CreateWorkflowConcurrencyOpts struct {
|
||||
// (required) the action id for getting the concurrency group
|
||||
Action string `validate:"required,actionId"`
|
||||
// (optional) the action id for getting the concurrency group
|
||||
Action *string `validate:"omitempty,actionId"`
|
||||
|
||||
// (optional) the maximum number of concurrent workflow runs, default 1
|
||||
MaxRuns *int32
|
||||
|
||||
// (optional) the strategy to use when the concurrency limit is reached, default CANCEL_IN_PROGRESS
|
||||
LimitStrategy *string `validate:"omitnil,oneof=CANCEL_IN_PROGRESS DROP_NEWEST QUEUE_NEWEST GROUP_ROUND_ROBIN"`
|
||||
|
||||
// (optional) a concurrency expression for evaluating the concurrency key
|
||||
Expression *string `validate:"omitempty,celworkflowrunstr"`
|
||||
}
|
||||
|
||||
func (o *CreateWorkflowVersionOpts) Checksum() (string, error) {
|
||||
|
||||
@@ -113,7 +113,7 @@ func GetCreateWorkflowRunOptsFromManual(
|
||||
AdditionalMetadata: additionalMetadata,
|
||||
}
|
||||
|
||||
if workflowVersion.ConcurrencyLimitStrategy.Valid {
|
||||
if workflowVersion.ConcurrencyLimitStrategy.Valid && workflowVersion.ConcurrencyGroupId.Valid {
|
||||
opts.GetGroupKeyRun = &CreateGroupKeyRunOpts{
|
||||
Input: input,
|
||||
}
|
||||
@@ -145,7 +145,7 @@ func GetCreateWorkflowRunOptsFromParent(
|
||||
|
||||
WithParent(parentId, parentStepRunId, childIndex, childKey, additionalMetadata, parentAdditionalMetadata)(opts)
|
||||
|
||||
if workflowVersion.ConcurrencyLimitStrategy.Valid {
|
||||
if workflowVersion.ConcurrencyLimitStrategy.Valid && workflowVersion.ConcurrencyGroupId.Valid {
|
||||
opts.GetGroupKeyRun = &CreateGroupKeyRunOpts{
|
||||
Input: input,
|
||||
}
|
||||
@@ -173,7 +173,7 @@ func GetCreateWorkflowRunOptsFromEvent(
|
||||
AdditionalMetadata: additionalMetadata,
|
||||
}
|
||||
|
||||
if workflowVersion.ConcurrencyLimitStrategy.Valid {
|
||||
if workflowVersion.ConcurrencyLimitStrategy.Valid && workflowVersion.ConcurrencyGroupId.Valid {
|
||||
opts.GetGroupKeyRun = &CreateGroupKeyRunOpts{
|
||||
Input: input,
|
||||
}
|
||||
@@ -203,7 +203,7 @@ func GetCreateWorkflowRunOptsFromCron(
|
||||
AdditionalMetadata: additionalMetadata,
|
||||
}
|
||||
|
||||
if workflowVersion.ConcurrencyLimitStrategy.Valid {
|
||||
if workflowVersion.ConcurrencyLimitStrategy.Valid && workflowVersion.ConcurrencyGroupId.Valid {
|
||||
opts.GetGroupKeyRun = &CreateGroupKeyRunOpts{
|
||||
Input: input,
|
||||
}
|
||||
@@ -232,7 +232,7 @@ func GetCreateWorkflowRunOptsFromSchedule(
|
||||
AdditionalMetadata: additionalMetadata,
|
||||
}
|
||||
|
||||
if workflowVersion.ConcurrencyLimitStrategy.Valid {
|
||||
if workflowVersion.ConcurrencyLimitStrategy.Valid && workflowVersion.ConcurrencyGroupId.Valid {
|
||||
opts.GetGroupKeyRun = &CreateGroupKeyRunOpts{
|
||||
Input: input,
|
||||
}
|
||||
@@ -389,8 +389,6 @@ type WorkflowRunAPIRepository interface {
|
||||
// Counts by status
|
||||
WorkflowRunMetricsCount(ctx context.Context, tenantId string, opts *WorkflowRunsMetricsOpts) (*dbsqlc.WorkflowRunsMetricsCountRow, error)
|
||||
|
||||
GetWorkflowRunInputData(tenantId, workflowRunId string) (map[string]interface{}, error)
|
||||
|
||||
// CreateNewWorkflowRun creates a new workflow run for a workflow version.
|
||||
CreateNewWorkflowRun(ctx context.Context, tenantId string, opts *CreateWorkflowRunOpts) (*dbsqlc.WorkflowRun, error)
|
||||
|
||||
@@ -414,6 +412,12 @@ func (e ErrDedupeValueExists) Error() string {
|
||||
return fmt.Sprintf("workflow run with dedupe value %s already exists", e.DedupeValue)
|
||||
}
|
||||
|
||||
type UpdateWorkflowRunFromGroupKeyEvalOpts struct {
|
||||
GroupKey *string
|
||||
|
||||
Error *string
|
||||
}
|
||||
|
||||
type WorkflowRunEngineRepository interface {
|
||||
RegisterCreateCallback(callback Callback[*dbsqlc.WorkflowRun])
|
||||
|
||||
@@ -429,6 +433,12 @@ type WorkflowRunEngineRepository interface {
|
||||
// CreateNewWorkflowRun creates a new workflow run for a workflow version.
|
||||
CreateNewWorkflowRun(ctx context.Context, tenantId string, opts *CreateWorkflowRunOpts) (string, error)
|
||||
|
||||
GetWorkflowRunInputData(tenantId, workflowRunId string) (map[string]interface{}, error)
|
||||
|
||||
ProcessWorkflowRunUpdates(ctx context.Context, tenantId string) (bool, error)
|
||||
|
||||
UpdateWorkflowRunFromGroupKeyEval(ctx context.Context, tenantId, workflowRunId string, opts *UpdateWorkflowRunFromGroupKeyEvalOpts) error
|
||||
|
||||
// GetWorkflowRunById returns a workflow run by id.
|
||||
GetWorkflowRunById(ctx context.Context, tenantId, runId string) (*dbsqlc.GetWorkflowRunRow, error)
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ const (
|
||||
ActionIDErr = "Invalid action ID. Action IDs must be in the format <integrationId>:<verb>"
|
||||
CronErr = "Invalid cron expression"
|
||||
DurationErr = "Invalid duration. Durations must be in the format <number><unit>, where unit is one of: 's', 'm', 'h'"
|
||||
CELExprErr = "Invalid CEL expression"
|
||||
)
|
||||
|
||||
type APIErrors gen.APIErrors
|
||||
@@ -132,6 +133,8 @@ func getErrorStr(errObj *ValidationErrObject) string {
|
||||
return errObj.SafeExternalError(CronErr)
|
||||
case "duration":
|
||||
return errObj.SafeExternalError(DurationErr)
|
||||
case "celworkflowrunstr":
|
||||
return errObj.SafeExternalError(CELExprErr)
|
||||
default:
|
||||
return errObj.SafeExternalError("")
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/hatchet-dev/hatchet/internal/cel"
|
||||
"github.com/hatchet-dev/hatchet/pkg/client/types"
|
||||
)
|
||||
|
||||
@@ -20,6 +21,8 @@ var CronRegex = regexp.MustCompile(`(@(annually|yearly|monthly|weekly|daily|hour
|
||||
func newValidator() *validator.Validate {
|
||||
validate := validator.New()
|
||||
|
||||
celParser := cel.NewCELParser()
|
||||
|
||||
_ = validate.RegisterValidation("hatchetName", func(fl validator.FieldLevel) bool {
|
||||
return NameRegex.MatchString(fl.Field().String())
|
||||
})
|
||||
@@ -62,6 +65,12 @@ func newValidator() *validator.Validate {
|
||||
return err == nil
|
||||
})
|
||||
|
||||
_ = validate.RegisterValidation("celworkflowrunstr", func(fl validator.FieldLevel) bool {
|
||||
_, err := celParser.ParseWorkflowString(fl.Field().String())
|
||||
|
||||
return err == nil
|
||||
})
|
||||
|
||||
return validate
|
||||
}
|
||||
|
||||
|
||||
+17
-3
@@ -157,10 +157,17 @@ type WorkflowJob struct {
|
||||
|
||||
type WorkflowConcurrency struct {
|
||||
fn GetWorkflowConcurrencyGroupFn
|
||||
expr *string
|
||||
maxRuns *int32
|
||||
limitStrategy *types.WorkflowConcurrencyLimitStrategy
|
||||
}
|
||||
|
||||
func Expression(expr string) *WorkflowConcurrency {
|
||||
return &WorkflowConcurrency{
|
||||
expr: &expr,
|
||||
}
|
||||
}
|
||||
|
||||
func Concurrency(fn GetWorkflowConcurrencyGroupFn) *WorkflowConcurrency {
|
||||
return &WorkflowConcurrency{
|
||||
fn: fn,
|
||||
@@ -206,8 +213,15 @@ func (j *WorkflowJob) ToWorkflow(svcName string, namespace string) types.Workflo
|
||||
}
|
||||
|
||||
if j.Concurrency != nil {
|
||||
w.Concurrency = &types.WorkflowConcurrency{
|
||||
ActionID: "concurrency:" + getFnName(j.Concurrency.fn), // TODO this should also be namespaced
|
||||
w.Concurrency = &types.WorkflowConcurrency{}
|
||||
|
||||
if j.Concurrency.fn != nil {
|
||||
actionId := "concurrency:" + getFnName(j.Concurrency.fn)
|
||||
w.Concurrency.ActionID = &actionId // TODO this should also be namespaced
|
||||
}
|
||||
|
||||
if j.Concurrency.expr != nil {
|
||||
w.Concurrency.Expression = j.Concurrency.expr
|
||||
}
|
||||
|
||||
if j.Concurrency.maxRuns != nil {
|
||||
@@ -259,7 +273,7 @@ func (j *WorkflowJob) ToActionMap(svcName string) map[string]any {
|
||||
res[actionId] = step.Function
|
||||
}
|
||||
|
||||
if j.Concurrency != nil {
|
||||
if j.Concurrency != nil && j.Concurrency.fn != nil {
|
||||
res["concurrency:"+getFnName(j.Concurrency.fn)] = j.Concurrency.fn
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
-- AlterEnum
|
||||
ALTER TYPE "InternalQueue" ADD VALUE 'WORKFLOW_RUN_UPDATE';
|
||||
|
||||
-- AlterEnum
|
||||
-- This migration adds more than one value to an enum.
|
||||
-- With PostgreSQL versions 11 and earlier, this is not possible
|
||||
-- in a single migration. This can be worked around by creating
|
||||
-- multiple migrations, each migration adding only one value to
|
||||
-- the enum.
|
||||
|
||||
|
||||
ALTER TYPE "StepRunEventReason" ADD VALUE 'WORKFLOW_RUN_GROUP_KEY_SUCCEEDED';
|
||||
ALTER TYPE "StepRunEventReason" ADD VALUE 'WORKFLOW_RUN_GROUP_KEY_FAILED';
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "StepRunEvent" DROP CONSTRAINT "StepRunEvent_stepRunId_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "StepRunEvent" ADD COLUMN "workflowRunId" UUID,
|
||||
ALTER COLUMN "stepRunId" DROP NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "WorkflowConcurrency" ADD COLUMN "concurrencyGroupExpression" TEXT;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "StepRunEvent_workflowRunId_idx" ON "StepRunEvent"("workflowRunId");
|
||||
+14
-7
@@ -593,6 +593,9 @@ model WorkflowConcurrency {
|
||||
getConcurrencyGroup Action? @relation(fields: [getConcurrencyGroupId], references: [id])
|
||||
getConcurrencyGroupId String? @db.Uuid
|
||||
|
||||
// A CEL expression for getting the concurrency group based on the input to the workflow.
|
||||
concurrencyGroupExpression String?
|
||||
|
||||
// the maximum number of concurrent workflow runs
|
||||
maxRuns Int @default(1)
|
||||
|
||||
@@ -1299,8 +1302,6 @@ model StepRun {
|
||||
childWorkflowRuns WorkflowRun[]
|
||||
childSchedules WorkflowTriggerScheduledRef[]
|
||||
|
||||
events StepRunEvent[]
|
||||
|
||||
@@index([tenantId])
|
||||
@@index([workerId])
|
||||
@@index([createdAt])
|
||||
@@ -1352,6 +1353,7 @@ model QueueItem {
|
||||
enum InternalQueue {
|
||||
WORKER_SEMAPHORE_COUNT
|
||||
STEP_RUN_UPDATE
|
||||
WORKFLOW_RUN_UPDATE
|
||||
}
|
||||
|
||||
model InternalQueueItem {
|
||||
@@ -1419,6 +1421,10 @@ enum StepRunEventReason {
|
||||
CANCELLED
|
||||
TIMEOUT_REFRESHED
|
||||
SLOT_RELEASED
|
||||
|
||||
// NOTE: not actually step run events, but the table is currently named StepRunEvent
|
||||
WORKFLOW_RUN_GROUP_KEY_SUCCEEDED
|
||||
WORKFLOW_RUN_GROUP_KEY_FAILED
|
||||
}
|
||||
|
||||
enum StepRunEventSeverity {
|
||||
@@ -1433,8 +1439,10 @@ model StepRunEvent {
|
||||
timeLastSeen DateTime @default(now())
|
||||
|
||||
// the parent step run
|
||||
stepRun StepRun @relation(fields: [stepRunId], references: [id], onDelete: Cascade, onUpdate: Cascade)
|
||||
stepRunId String @db.Uuid
|
||||
stepRunId String? @db.Uuid
|
||||
|
||||
// the parent workflow run
|
||||
workflowRunId String? @db.Uuid
|
||||
|
||||
// the event reason
|
||||
reason StepRunEventReason
|
||||
@@ -1448,9 +1456,8 @@ model StepRunEvent {
|
||||
|
||||
data Json?
|
||||
|
||||
// id - timeFirstSeen uniue index
|
||||
|
||||
@@index([stepRunId]) // only on wfr id
|
||||
@@index([stepRunId])
|
||||
@@index([workflowRunId])
|
||||
}
|
||||
|
||||
model StepRunResultArchive {
|
||||
|
||||
@@ -10,3 +10,5 @@ ALTER TABLE "InternalQueueItem" ADD CONSTRAINT "InternalQueueItem_priority_check
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "StepRun_jobRunId_status_tenantId_idx"
|
||||
ON "StepRun" ("jobRunId", "status", "tenantId")
|
||||
WHERE "status" = 'PENDING';
|
||||
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "WorkflowRun_parentStepRunId" ON "WorkflowRun"("parentStepRunId" ASC);
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
-- atlas:txmode none
|
||||
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "WorkflowRun_parentStepRunId" ON "WorkflowRun"("parentStepRunId" ASC);
|
||||
|
||||
-- Add value to enum type: "StepRunEventReason"
|
||||
ALTER TYPE "StepRunEventReason" ADD VALUE 'WORKFLOW_RUN_GROUP_KEY_SUCCEEDED';
|
||||
-- Add value to enum type: "StepRunEventReason"
|
||||
ALTER TYPE "StepRunEventReason" ADD VALUE 'WORKFLOW_RUN_GROUP_KEY_FAILED';
|
||||
-- Add value to enum type: "InternalQueue"
|
||||
ALTER TYPE "InternalQueue" ADD VALUE 'WORKFLOW_RUN_UPDATE';
|
||||
-- Modify "StepRunEvent" table
|
||||
ALTER TABLE "StepRunEvent" DROP CONSTRAINT "StepRunEvent_stepRunId_fkey", ALTER COLUMN "stepRunId" DROP NOT NULL, ADD COLUMN "workflowRunId" uuid NULL;
|
||||
-- Create index "StepRunEvent_workflowRunId_idx" to table: "StepRunEvent"
|
||||
CREATE INDEX "StepRunEvent_workflowRunId_idx" ON "StepRunEvent" ("workflowRunId");
|
||||
-- Modify "WorkflowConcurrency" table
|
||||
ALTER TABLE "WorkflowConcurrency" ADD COLUMN "concurrencyGroupExpression" text NULL;
|
||||
@@ -1,4 +1,4 @@
|
||||
h1:GONXnb4KX2gX139WgjSkVzSS2yGkT+MXqmCtgO3ulMg=
|
||||
h1:TwaCvaPgsVfs199JWuoIa/1ipf3RIgAGfH76Wzm/4dw=
|
||||
20240115180414_init.sql h1:Ef3ZyjAHkmJPdGF/dEWCahbwgcg6uGJKnDxW2JCRi2k=
|
||||
20240122014727_v0_6_0.sql h1:o/LdlteAeFgoHJ3e/M4Xnghqt9826IE/Y/h0q95Acuo=
|
||||
20240126235456_v0_7_0.sql h1:KiVzt/hXgQ6esbdC6OMJOOWuYEXmy1yeCpmsVAHTFKs=
|
||||
@@ -56,3 +56,4 @@ h1:GONXnb4KX2gX139WgjSkVzSS2yGkT+MXqmCtgO3ulMg=
|
||||
20240911124017_v0.44.6.sql h1:7MlkRZpRUra7GUPSYfFzqDSZGM1SKlP1j81xMHyptqc=
|
||||
20240911201831_v0.44.7.sql h1:rBiOx3qNLvl9lCedK6dlf6yTX3y+xCcmUJNEXPG8YYc=
|
||||
20240916115647_v0.44.8.sql h1:1D5fmikdME61lwN1/EbBTmGcKzpqESZUmfoHvmOeZl4=
|
||||
20240918162532_v0.45.0.sql h1:pOhBg/58SnD8qBpDx9OdxTFfjRxEanJrJF7rLEvUFSY=
|
||||
|
||||
+11
-7
@@ -2,7 +2,7 @@
|
||||
CREATE TYPE "ConcurrencyLimitStrategy" AS ENUM ('CANCEL_IN_PROGRESS', 'DROP_NEWEST', 'QUEUE_NEWEST', 'GROUP_ROUND_ROBIN');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "InternalQueue" AS ENUM ('WORKER_SEMAPHORE_COUNT', 'STEP_RUN_UPDATE');
|
||||
CREATE TYPE "InternalQueue" AS ENUM ('WORKER_SEMAPHORE_COUNT', 'STEP_RUN_UPDATE', 'WORKFLOW_RUN_UPDATE');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "InviteLinkStatus" AS ENUM ('PENDING', 'ACCEPTED', 'REJECTED');
|
||||
@@ -20,7 +20,7 @@ CREATE TYPE "LimitResource" AS ENUM ('WORKFLOW_RUN', 'EVENT', 'WORKER', 'CRON',
|
||||
CREATE TYPE "LogLineLevel" AS ENUM ('DEBUG', 'INFO', 'WARN', 'ERROR');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "StepRunEventReason" AS ENUM ('REQUEUED_NO_WORKER', 'REQUEUED_RATE_LIMIT', 'SCHEDULING_TIMED_OUT', 'ASSIGNED', 'STARTED', 'FINISHED', 'FAILED', 'RETRYING', 'CANCELLED', 'TIMED_OUT', 'REASSIGNED', 'SLOT_RELEASED', 'TIMEOUT_REFRESHED', 'RETRIED_BY_USER', 'SENT_TO_WORKER');
|
||||
CREATE TYPE "StepRunEventReason" AS ENUM ('REQUEUED_NO_WORKER', 'REQUEUED_RATE_LIMIT', 'SCHEDULING_TIMED_OUT', 'ASSIGNED', 'STARTED', 'FINISHED', 'FAILED', 'RETRYING', 'CANCELLED', 'TIMED_OUT', 'REASSIGNED', 'SLOT_RELEASED', 'TIMEOUT_REFRESHED', 'RETRIED_BY_USER', 'SENT_TO_WORKER', 'WORKFLOW_RUN_GROUP_KEY_SUCCEEDED', 'WORKFLOW_RUN_GROUP_KEY_FAILED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "StepRunEventSeverity" AS ENUM ('INFO', 'WARNING', 'CRITICAL');
|
||||
@@ -396,12 +396,13 @@ CREATE TABLE "StepRunEvent" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"timeFirstSeen" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"timeLastSeen" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"stepRunId" UUID NOT NULL,
|
||||
"stepRunId" UUID,
|
||||
"reason" "StepRunEventReason" NOT NULL,
|
||||
"severity" "StepRunEventSeverity" NOT NULL,
|
||||
"message" TEXT NOT NULL,
|
||||
"count" INTEGER NOT NULL,
|
||||
"data" JSONB
|
||||
"data" JSONB,
|
||||
"workflowRunId" UUID
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
@@ -736,6 +737,7 @@ CREATE TABLE "WorkflowConcurrency" (
|
||||
"getConcurrencyGroupId" UUID,
|
||||
"maxRuns" INTEGER NOT NULL DEFAULT 1,
|
||||
"limitStrategy" "ConcurrencyLimitStrategy" NOT NULL DEFAULT 'CANCEL_IN_PROGRESS',
|
||||
"concurrencyGroupExpression" TEXT,
|
||||
|
||||
CONSTRAINT "WorkflowConcurrency_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
@@ -1074,6 +1076,9 @@ CREATE UNIQUE INDEX "StepRunEvent_id_key" ON "StepRunEvent"("id" ASC);
|
||||
-- CreateIndex
|
||||
CREATE INDEX "StepRunEvent_stepRunId_idx" ON "StepRunEvent"("stepRunId" ASC);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "StepRunEvent_workflowRunId_idx" ON "StepRunEvent"("workflowRunId" ASC);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "StepRunResultArchive_id_key" ON "StepRunResultArchive"("id" ASC);
|
||||
|
||||
@@ -1422,9 +1427,6 @@ ALTER TABLE "StepRun" ADD CONSTRAINT "StepRun_tickerId_fkey" FOREIGN KEY ("ticke
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "StepRun" ADD CONSTRAINT "StepRun_workerId_fkey" FOREIGN KEY ("workerId") REFERENCES "Worker"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "StepRunEvent" ADD CONSTRAINT "StepRunEvent_stepRunId_fkey" FOREIGN KEY ("stepRunId") REFERENCES "StepRun"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "StepRunResultArchive" ADD CONSTRAINT "StepRunResultArchive_stepRunId_fkey" FOREIGN KEY ("stepRunId") REFERENCES "StepRun"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
@@ -1629,3 +1631,5 @@ ALTER TABLE "InternalQueueItem" ADD CONSTRAINT "InternalQueueItem_priority_check
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "StepRun_jobRunId_status_tenantId_idx"
|
||||
ON "StepRun" ("jobRunId", "status", "tenantId")
|
||||
WHERE "status" = 'PENDING';
|
||||
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "WorkflowRun_parentStepRunId" ON "WorkflowRun"("parentStepRunId" ASC);
|
||||
|
||||
Reference in New Issue
Block a user