Skip to content

TS/runtime-5: align virtual/real time in all types of scheduled task category#10305

Merged
feiyang3cat merged 3 commits into
temporalio:mainfrom
feiyang3cat:ts/patch-5
May 26, 2026
Merged

TS/runtime-5: align virtual/real time in all types of scheduled task category#10305
feiyang3cat merged 3 commits into
temporalio:mainfrom
feiyang3cat:ts/patch-5

Conversation

@feiyang3cat
Copy link
Copy Markdown
Contributor

@feiyang3cat feiyang3cat commented May 18, 2026

What changed?

  • mutable_state_impl.go
    • AddTasks: drop-check gate widened to all CategoryTypeScheduled tasks (was timers only); comparison
      uses ms.Now() (virtual) instead of wall.
    • New ToRealTime(virtual) → wall centralizes the conversion.
    • SetSpeculativeWorkflowTaskTimeoutTask converts to wall via ToRealTime before enqueuing.
    • accumulatedSkippedDuration simplified to nil-safe proto getter.
  • timer_queue_{active,standby}_task_executor.go: (1) heartbeat-dedup compares wall-vs-wall via
    ToRealTime(heartbeatTimeoutVis) (was mixed frames), (2) for activity timeout/user timer time check, (3) for run time our retry, inherit time skipping config
  • task_generator.go: TODO marking ChasmTaskPure
  • interfaces/mutable_state.go: adds ToRealTime; documents virtual-frame contract on AddTasks,
    Now, SetSpeculativeWorkflowTaskTimeoutTask.

Why?

Under time skipping, virtual time inside mutable state can run ahead of wall time, but scheduled-task
firing still runs on wall time. Each crossing needs explicit conversion:

  • Tasks leaving mutable state for the scheduled-task queues must be converted to wall time.
  • Validation of generated/fired tasks must reference virtual (mutable-state) time.

Before this change, virtual and wall values were silently compared — harmless pre-skipping, but now lets
the wrong tasks get dropped/kept and stale heartbeat tasks pass dedup.

How did you test it?

  • built
  • run locally and tested manually
  • covered by existing tests
  • added new unit test(s)
  • added new functional test(s)

@feiyang3cat feiyang3cat requested review from a team as code owners May 18, 2026 01:59
@feiyang3cat feiyang3cat changed the title ts/patch-5: align virtual time and real time in timer task execution ts/patch: align virtual time and real time in timer task execution May 18, 2026
@feiyang3cat feiyang3cat force-pushed the ts/patch-5 branch 3 times, most recently from 3d50bdf to a3f1761 Compare May 18, 2026 03:21
@feiyang3cat feiyang3cat changed the title ts/patch: align virtual time and real time in timer task execution ts/patch: align virtual time and real time in scheduled task execution May 18, 2026
@feiyang3cat feiyang3cat force-pushed the ts/patch-5 branch 2 times, most recently from 4ab596d to cca239e Compare May 18, 2026 05:13
@feiyang3cat feiyang3cat changed the title ts/patch: align virtual time and real time in scheduled task execution TS/patch: align virtual time and real time in scheduled task execution May 18, 2026
@feiyang3cat feiyang3cat changed the title TS/patch: align virtual time and real time in scheduled task execution TS/runtime: align virtual/real time in all types of scheduled task category May 18, 2026
@feiyang3cat feiyang3cat changed the title TS/runtime: align virtual/real time in all types of scheduled task category TS/runtime-5: align virtual/real time in all types of scheduled task category May 18, 2026
@feiyang3cat feiyang3cat force-pushed the ts/patch-5 branch 6 times, most recently from 8c53840 to d848ebf Compare May 18, 2026 20:54
Comment thread service/history/timer_queue_standby_task_executor.go
// real wall-clock, so convert here — callers outside MutableState don't see the virtual
// vs. real distinction. The CategoryTypeScheduled drop-check above runs first so it
// compares virtual-vs-virtual (now is also virtual).
if skip > 0 && category == tasks.CategoryTimer {
Copy link
Copy Markdown
Contributor Author

@feiyang3cat feiyang3cat May 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

though we add other scheduled timer task types in, the executors of archival and speculative tasks don't validate the fire time, so for those tasks the executor files are untouched

@feiyang3cat feiyang3cat force-pushed the ts/patch-5 branch 2 times, most recently from 7a2bf1f to f0690d9 Compare May 18, 2026 21:51
// compares virtual-vs-virtual (now is also virtual).
if skip > 0 && category == tasks.CategoryTimer {
if skip > 0 && category.Type() == tasks.CategoryTypeScheduled {
task.SetVisibilityTime(task.GetVisibilityTime().Add(-skip))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could you also use ms.ToRealTime here? might also be able to fold fast return when skip == 0 case into ToRealTime

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

return nil, serviceerror.NewInternal(errString)
}

if queues.IsTimeExpired(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function uses wall time in task.GetKey().FireTime, but virtual time for rest of parameters

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, I saw the link you pasted below about the origin of this function. I think I misunderstood the use of this function, and have changed all the three time points to real time. pls have another look. thanks !

return nil, serviceerror.NewInternal(errString)
}

if queues.IsTimeExpired(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above^^

ctx context.Context,
timerTask *tasks.UserTimerTask,
) error {
referenceTime := t.Now()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yycptt, any reason why you set this here, rather than inside action? Reading through https://github.com/temporalio/temporal/pull/7030/changes, seems like it is fine to do it inside.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(btw: there is no need to change this line after I switched to real time for comparison in task queues

@feiyang3cat feiyang3cat force-pushed the ts/patch-5 branch 5 times, most recently from 3b060f0 to 0f7227d Compare May 25, 2026 18:30
@feiyang3cat feiyang3cat force-pushed the ts/patch-5 branch 8 times, most recently from 35ce9d8 to bb473c3 Compare May 26, 2026 06:35
// AddTasks adds tasks to the mutable state.
// For scheduled tasks (any CategoryTypeScheduled — e.g. timer, archival), if time has been
// skipped (i.e. the virtual time of this mutable state is ahead of wall-clock time), the
// scheduled time of the task is adjusted to wall-clock time, as the dispatch queues run
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: for clarity, it is worth to specify that the virtual time should be passed in, but it will be adjusted to the wall-clock

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@feiyang3cat feiyang3cat enabled auto-merge (squash) May 26, 2026 19:53
@feiyang3cat feiyang3cat merged commit fdacc2c into temporalio:main May 26, 2026
48 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants