sql-job-queue

Build a dependency-driven DB-backed job queue with atomic leasing on SQLAlchemy 2.x.

1|1|Updated May 24, 2026
One-click install
npx skills add https://github.com/bm629/agent-skills --skill sql-job-queue-bm629
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: sql-job-queue
Source: https://github.com/bm629/agent-skills/tree/main/skills/sql-job-queue
Command: npx skills add https://github.com/bm629/agent-skills --skill sql-job-queue-bm629

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill requires sqlalchemy, and includes references (resource) components.

What problem does it solve? Building a background job queue without a broker means solving atomic job claiming, crash recovery, and dependency-driven readiness yourself — and each SQL dialect (SQLite, PostgreSQL, MySQL) locks differently, so naive implementations double-dispatch jobs or silently fail on SQLite. ## Core Features & Use Cases - Per-dialect atomic lease: Implements the claim transaction with FOR UPDATE SKIP LOCKED on PostgreSQL and MySQL 8+ versus BEGIN IMMEDIATE on SQLite, with dialect detection and the MySQL isolation-level caveats handled. - Crash-resume and fair scheduling: Covers heartbeat-based lease renewal, stale-lease reclaim, hung-job timeouts, and weighted fair-share allocation across job groups. - Use Case: You need an embeddable, single-box task scheduler where jobs form a dependency DAG and the relational database is the only durable store — for example, orchestrating long-running report-generation jobs in a desktop app backed by SQLite that must also run on PostgreSQL in production. ## Quick Start Use the sql-job-queue skill to build a dependency-driven job scheduler on SQLAlchemy with atomic leasing across SQLite, PostgreSQL, and MySQL.

Frequently Asked Questions about sql-job-queue

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I build a job queue in SQLAlchemy without Celery or Redis?

Use a jobs table plus a job_deps edge table for the dependency DAG, a ready-set query to find runnable jobs, and an atomic lease transaction to claim them. A tick loop scans, ranks by fair-share, leases, dispatches, and reclaims stale leases — no broker required.

How does SELECT FOR UPDATE SKIP LOCKED work for job queues?

FOR UPDATE SKIP LOCKED lets a worker lock and claim a ready row while skipping rows already locked by other workers, so concurrent claims never pick the same job. It works on PostgreSQL and MySQL 8.0+ with InnoDB, but is a syntax error on MySQL 5.7.

Does SQLAlchemy with_for_update work on SQLite?

No, with_for_update is a silent no-op on SQLite because SQLite has no row-level locks — it does not error, it just does not lock. Use BEGIN IMMEDIATE to take the database write lock at transaction start so the claim serializes across workers.

Why does my MySQL job queue claim miss newly inserted jobs?

MySQL defaults to REPEATABLE READ isolation, so a claim SELECT reads a snapshot taken at transaction start and can miss rows committed afterward. Set READ COMMITTED for the claim transaction so each statement sees freshly committed ready rows.

How do I recover jobs after a worker crashes?

Workers renew a lease with a heartbeat while running; a dead worker stops renewing, so its lease expires. A reclaim sweep each tick returns expired-lease jobs to the ready state, while a separate per-dispatch timeout bounds hung-but-alive jobs.

When should I use Celery instead of a database-backed queue?

Use a broker like Celery or RabbitMQ for short fire-and-forget tasks with static enqueue and multi-machine fan-out. A DB-backed queue fits long-running stateful jobs with dependency-driven readiness on a single box where the database is the only durable store.