Skip to content

SQLite task visibility timeout mixes milliseconds and seconds #32

Description

@djgrant

Problem

SqliteTaskQueue.process() calculates visibilityTimeout with Date.now() + VISIBILITY_WINDOW, producing a millisecond timestamp, and writes it to task_queue.visible_from.

TaskQueueDao.getNextTask() and getTaskCount() compare visible_from with strftime('%s', 'now'), which is a Unix timestamp in seconds.

After a worker claims a task, visible_from is therefore approximately 1,000 times larger than the value used by subsequent visibility queries. If the worker crashes before removing the task or making it visible, the task remains hidden for roughly 55,000 years instead of the intended five minutes.

Affected code:

  • packages/sqlite-runtime/src/sqlite-task-queue.ts: Date.now() + VISIBILITY_WINDOW
  • packages/sqlite-runtime/src/dao/task-queue-dao.ts: visible_from < strftime('%s', 'now')

This is present in Yieldstar 0.5.0 and on main.

Expected behavior

The stored visibility timestamp and SQL comparison should use the same unit. Either store Unix seconds throughout or compare millisecond values throughout, including the column default and task-count query.

Suggested regression test

  1. Add and claim a task.
  2. Confirm it is temporarily invisible.
  3. Advance beyond the configured visibility window or set the clock accordingly.
  4. Confirm a newly constructed SQLite task queue can claim the task again.

Impact

This breaks unattended crash recovery for an in-flight SQLite queue task. A durable workflow wake-up can remain stranded after a process crash even though its intended visibility timeout has elapsed.

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