Skip to content

TimerResource replays every missed interval after an idle redraw #166

Description

@zcourts

Problem

Runtime::tick_resource_timers dispatches one action for every interval missed since next_fire_at:

while now >= *next_fire_at {
    ticks.push((action.clone(), payload.clone()));
    *next_fire_at = next_fire_at.saturating_add(interval_ms);
}

On the Web shell, the runtime clock advances by the elapsed wall time at the next redraw. If a tab has no redraw for 150 seconds, a two-second TimerResource dispatches approximately 75 actions at once on the next user interaction. A timer used for bounded network repair therefore becomes a request burst.

The same behavior is present in the 0.11.0 release and the current 0.11.1 release source.

Minimal reproduction

  1. Declare a TimerResource with a two-second interval and an action that increments a counter or starts a job.
  2. Let the Web app remain idle without redraws for approximately 30 seconds.
  3. Trigger one redraw/user interaction.
  4. Observe approximately 15 timer actions dispatched in that single tick.

The core behavior can also be reproduced deterministically by advancing a runtime clock by a multiple of the timer interval in one Runtime::tick call.

Expected behavior

A UI interval timer should coalesce missed intervals by default: dispatch at most one action when the runtime resumes, then schedule the next firing from the current runtime time. If catch-up replay is required for simulation use cases, it should be an explicit policy with a bounded maximum.

A focused test should cover a large clock advance and assert one coalesced dispatch for the normal timer policy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions