229
)
230
231
>
func SchedulerWorkflow(ctx workflow.Context, args *schedulespb.StartScheduleArgs) error {
workflow.go
232
>
disabled := func() bool { return false }
233
>
dc := dynamicconfig.NewNoopCollection()
234
>
specBuilder := NewSpecBuilder(
235
>
dynamicconfig.SchedulerSpecWarnIterations.Get(dc),
236
>
dynamicconfig.SchedulerSpecMaxIterations.Get(dc),
237
>
)
238
>
return schedulerWorkflowWithSpecBuilder(ctx, args, specBuilder, disabled, disabled)
239
}
240
241
>
func schedulerWorkflowWithSpecBuilder(ctx workflow.Context, args *schedulespb.StartScheduleArgs, specBuilder *SpecBuilder, enableCHASMMigration func() bool, migrateWithRunningWorkflows func() bool) error {
workflow.go
242
>
scheduler := &scheduler{
243
>
StartScheduleArgs: args,
244
>
ctx: ctx,
245
>
a: nil,
246
>
logger: sdklog.With(workflow.GetLogger(ctx), "wf-namespace", args.State.Namespace, "schedule-id", args.State.ScheduleId),
247
>
metrics: workflow.GetMetricsHandler(ctx).WithTags(map[string]string{
248
>
"namespace": args.State.Namespace,
249
>
metrics.ScheduleBackendTag: metrics.ScheduleBackendLegacy,
250
>
}),
251
>
specBuilder: specBuilder,
252
>
enableCHASMMigration: enableCHASMMigration,
253
>
migrateWithRunningWorkflows: migrateWithRunningWorkflows,
254
>
}
255
>
return scheduler.run()
256
>
}
257
259
>
s.updateTweakables()
260
>
s.ensureFields()
261
>
s.compileSpec()
262
>
263
>
if err := workflow.SetQueryHandler(s.ctx, QueryNameDescribe, s.handleDescribeQuery); err != nil {
264
return err
265
}
266
>
if err := workflow.SetQueryHandler(s.ctx, QueryNameListMatchingTimes, s.handleListMatchingTimesQuery); err != nil {
workflow.go
267
return err
268
}
269
270
>
if s.State.LastProcessedTime == nil {
workflow.go
271
>
// log these as json since it's more readable than the Go representation
workflow.go
272
>
specJson, _ := protojson.Marshal(s.Schedule.Spec)
273
>
policiesJson, _ := protojson.Marshal(s.Schedule.Policies)
274
>
s.logger.Info("Starting schedule", "spec", string(specJson), "policies", string(policiesJson))
275
>
276
>
s.State.LastProcessedTime = timestamppb.New(s.now())
277
>
s.State.ConflictToken = InitialConflictToken
278
>
s.Info.CreateTime = s.State.LastProcessedTime
279
>
280
>
s.recordActionPayloadMetrics()
281
>
}
282
283
// A schedule may be created with an initial Patch, e.g. start one immediately. Put that in
284
// the state so it takes effect below.
286
>
s.InitialPatch = nil
287
>
288
>
iters := s.tweakables.IterationsBeforeContinueAsNew
289
>
for {
290
>
info := workflow.GetInfo(s.ctx)
291
>
suggestContinueAsNew := info.GetCurrentHistoryLength() >= impossibleHistorySize
292
>
if s.tweakables.IterationsBeforeContinueAsNew > 0 {
293
>
// forceCAN must be checked here too, not just in the else branch,
workflow.go
294
>
// so that the force-continue-as-new signal is honored regardless
295
>
// of whether IterationsBeforeContinueAsNew is set.
296
>
suggestContinueAsNew = suggestContinueAsNew || iters <= 0 || s.forceCAN
297
>
iters--
299
suggestContinueAsNew = suggestContinueAsNew || info.GetContinueAsNewSuggested() || s.forceCAN
300
}
301
>
if suggestContinueAsNew && s.pendingUpdate == nil && s.pendingPatch == nil {
workflow.go
303
}
304
305
>
t1 := timestamp.TimeValue(s.State.LastProcessedTime)
workflow.go
306
>
t2 := s.now()
307
>
if t2.Before(t1) {
308
// Time went backwards. Currently this can only happen across a continue-as-new boundary.
309
s.logger.Warn("Time went backwards", "from", t1, "to", t2)
310
t2 = t1
311
}
312
>
nextWakeup, lastAction := s.processTimeRange(
workflow.go
313
>
t1, t2,
314
>
// resolve this to the schedule's policy as late as possible
315
>
enumspb.SCHEDULE_OVERLAP_POLICY_UNSPECIFIED,
316
>
false,
317
>
nil,
318
>
)
319
>
if s.hasMinVersion(UseLastAction) {
320
>
s.State.LastProcessedTime = timestamppb.New(lastAction)
321
>
} else {
322
s.State.LastProcessedTime = timestamppb.New(t2)
323
}
324
// handle signals after processing time range that just elapsed
325
>
scheduleChanged := s.processSignals()
workflow.go
326
>
if scheduleChanged {
327
// need to calculate sleep again
328
nextWakeup, _ = s.processTimeRange(