Skip to content

Bug: df.wait_for_schedule computes cron wait at DSL time, not execution time #130

@pinodeca

Description

@pinodeca

Summary

df.wait_for_schedule() in src/dsl.rs pre-computes wait_seconds at graph construction time (when df.start() is called), not at execution time. If there is any delay between df.start() and when the background worker runs the WAIT_SCHEDULE node, the wait will be too short and the function may wake before the intended cron tick.

// Compute wait duration NOW (at DSL time) for deterministic orchestration replay
let now = Utc::now();
let next = schedule.upcoming(Utc).next()...
let duration_secs = (next - now).num_seconds().max(0) as u64;

The stored JSON is {"wait_seconds": N} — a fixed offset, not a target timestamp.

Severity

Low — the code comment acknowledges the trade-off (deterministic replay). Real-world impact is bounded by BGW queue latency (typically seconds), but under load the window can grow.

Root Cause / Trade-off

Pre-computing makes duroxide replay safe because the orchestration must be deterministic. Calling Utc::now() inside the orchestration is forbidden. The fix must compute remaining wait inside an activity (which is allowed I/O).

Fix

Store the target timestamp (next cron tick) instead of wait_seconds. Add an activity (compute_cron_wait) that receives the target timestamp, computes max(0, target - now()), and returns the seconds to wait. The orchestration schedules that activity first, then passes the result to schedule_timer. This keeps the orchestration deterministic while correctly measuring remaining time at actual execution.

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions