Description Design Constraints:
Keep execution local to Rage workers. This is not a distributed job executor.
Queue can depend on backend. Backend must not depend on queue.
Keep scheduling, execution, retries, and task removal in the queue layer.
Use Active Record connection handling for all SQL backend database access. Do not use raw pg connections.
Keep :sql as the logical backend identifier. Version one requires Active Record and supports PostgreSQL only.
Validate Active Record availability and PostgreSQL compatibility when :sql is selected. MySQL and SQLite are follow up work.
Do not add Active Record as a global Rage dependency. Applications not using :sql must keep current behavior.
Do not create or migrate tables at boot.
Preserve at least once delivery semantics.
Store only authenticated encrypted task payloads in SQL tables. Verify and decrypt before calling Marshal.load.
Derive a Deferred specific encryption key from Rage.config.secret_key_base and support fallback secret keys for rotation.
Support current deferred backend contract and add dead task APIs without changing :disk or nil behavior.
Treat PostgreSQL as the initial correctness target for task claiming and recovery.
Implementation Plan:
Phase 1. Internal Deferred hooks and backend contract:
Phase 2. SQL backend scaffold and configuration:
Phase 3. SQL schema, payload codec, and backend private models:
Phase 4. Core live task persistence:
Phase 5. Claiming and worker lifecycle:
Phase 6. Dead task integration:
Phase 7. Validation, docs, and follow up:
Add PostgreSQL backed external specs using existing test infrastructure.
Cover encrypted round trips, key rotation, tampered payload handling, dead task moves, multi worker claims, delayed tasks, and stale worker recovery.
Add docs for PostgreSQL only version one support, Active Record setup, migrations, key management, failure model, and operational notes.
Add changelog entry once feature is complete end to end.
Evaluate MySQL support only after the PostgreSQL backed path is correct and merged.
Reactions are currently unavailable
You can’t perform that action at this time.
Design Constraints:
pgconnections.:sqlas the logical backend identifier. Version one requires Active Record and supports PostgreSQL only.:sqlis selected. MySQL and SQLite are follow up work.:sqlmust keep current behavior.Marshal.load.Rage.config.secret_key_baseand support fallback secret keys for rotation.:diskornilbehavior.Implementation Plan:
Phase 1. Internal Deferred hooks and backend contract:
add,remove, andpending_tasks.add_dead_task,list_dead_tasks,find_dead_task, andremove_dead_tasks.:diskandnilbehavior unchanged.Phase 2. SQL backend scaffold and configuration:
Rage::Deferred::Backends::Sql.config.deferred.backend = :sql, ...parsing and option validation.:sqlis selected.ActiveRecord::Base.connection_pool.with_connectionfor every database operation.Phase 3. SQL schema, payload codec, and backend private models:
rage_deferred_workers.rage_deferred_tasks.rage_deferred_dead_tasks.Marshal.dump, then encrypts and authenticates the payload before storage.secret_key_baseonly when:sqlis enabled and use fallback keys when reading existing payloads after key rotation.Phase 4. Core live task persistence:
add(context, publish_at:, task_id:).remove(task_id).pending_tasksrecovery for due rows.Marshal.load.task_idacross retries so another enqueue updates the same logical task row.Phase 5. Claiming and worker lifecycle:
Phase 6. Dead task integration:
add_dead_taskbefore live row removal, matching queue ordering.list_dead_tasks,find_dead_task, andremove_dead_tasks.Marshal.loadfor a payload that fails authentication or decryption.Phase 7. Validation, docs, and follow up: