Uh oh!
There was an error while loading. Please reload this page.
local dev: sqlite queue for cross-process - #88
Merged
Conversation
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Managed SQLite queue for reliable local cross-process delivery
Summary
Some history: The default local development previously had a shared memory + IPC implementation for queues, but I eventually removed this in favor of a single-process memory-only queue implementation that worked well for
hot dev. This change allowed for a simpler design, but gave up the ability to havehot eval 'send("my-event", ...)'run from another process in local development unless you were using theredisqueue type locally. This PR fixes this with a sqlite queue + in-process message channel + out-of-process backup polling.Adds a managed SQLite queue backend and makes it the default queue for Hot projects.
SQLite is the queue store. An in-process channel carries durable message IDs for immediate same-process wakeups, while a short SQLite polling interval discovers messages produced by sibling processes. This fixes event delivery between commands such as
hot dev,hot run, andhot evalwithout requiring Redis.Motivation
The previous in-memory default only worked when producers and consumers shared a process. Separate local commands could enqueue into isolated memory queues, causing events to be silently lost.
The new default provides:
Queue configuration
Introduces
queue.type = "sqlite".sqlite: managed project-local queue and the new in-project defaultmemory: explicitly selected, single-process-only queueredis: distributed/production queuenone: queue disabled where supportedsqlite3is not accepted as an alias.Commands outside a Hot project continue to resolve the queue as disabled where appropriate.
Managed SQLite backend
.hot/db/queue/db.uriand application database migrationsUPDATE ... RETURNINGclaims to prevent duplicate processingQueue lifecycle semantics
Standalone services
Standalone
hot api,hot app,hot worker,hot task-worker, andhot schedulerprocesses can share the SQLite queue.Queue data survives process restarts, and expired processing leases are recovered for retry.
Redis-style startup retention APIs are intentionally non-destructive for SQLite. Startup windows and stale-backlog purges do not delete ready messages or another worker’s active lease because SQLite contains the authoritative copy of the work.
hot devhot devpreserves the session-scoped behavior of the former memory queue:Standalone SQLite services use shared queue-session locks and cannot overlap a running
hot dev, preventing a dev restart from clearing their active work.hot runandhot evalcan still publish events into the active dev session.hot testIntegration-mode
hot testexplicitly uses the memory queue because its services run in one process. This isolates tests from a siblinghot devand avoids accumulating per-run SQLite files.Recovery and dead-letter handling
Orphan recovery now distinguishes between:
SQLite returns the durable payloads for both outcomes.
This allows:
hot devreconciliation to include dead-lettered event snapshotsExpired leases are no longer moved to the DLQ invisibly during an ordinary claim. Terminal transitions happen through explicit recovery, where the application state can be reconciled.
Dropped, cancelled, or panicking handlers consume paced retries rather than entering a tight redelivery loop.
Event publisher reliability
hot runandhot evalsurface enqueue/drain failures to the userQueue administration
hot queue statussupports managed SQLite queues and reports:hot queue clearclears managed SQLite queue rows.Documentation
Updates configuration documentation and the full configuration template with:
hot devreset behaviorCompatibility
queue.type = "redis"deployments continue to work