QueueCTL is a modular command-line job queue manager built with Python, Typer, SQLite, and Docker.
It provides a lightweight yet powerful framework to enqueue shell commands, manage workers, handle retries, and inspect a Dead Letter Queue (DLQ) β all from the CLI.
- Features
- Setup Instructions
- Usage Examples
- Architecture Overview
- Assumptions & Trade-offs
- Testing Instructions
- Project Structure
- License
- Author
- π CLI-based job queue management with Typer
- π SQLite database for lightweight persistence
- π Automatic retry logic with exponential backoff
- π Dead Letter Queue (DLQ) for failed jobs
- βοΈ Configurable settings (max retries, worker count, etc.)
- π³ Docker support with persistent volumes
- π· Multi-worker architecture for concurrent job processing
- π‘οΈ Graceful shutdown handling
- π¨ Rich CLI output with tables and status indicators
- Python 3.11+
- Docker & Docker Compose (for containerized setup)
pip(Python package manager)
# Clone the repository
git clone https://github.com/<your-username>/queuectl.git
cd queuectl
# Create a virtual environment
python -m venv venv
source venv/bin/activate # (Linux/Mac)
venv\Scripts\activate # (Windows)
# Install dependencies
pip install -e .
# Initialize database (automatically happens on first command)
queuectl list# Build the Docker image
docker build -t queuectl .
# Run interactively
docker run -it queuectl bash
# Inside container, run commands
queuectl enqueue "echo 'Hello from Docker!'"
queuectl list --state pendingβ
Persistent Data:
A Docker volume queuectl-data ensures your SQLite database persists between container runs.
# Using Docker Compose (if available)
docker-compose up -d
docker-compose exec queuectl queuectl listqueuectl enqueue "echo 'Test Job'" --max-retries 3Output:
Job added with ID: 5f07c123-45ef-42b8-88cd-8e6e33bd4e5d
# List all jobs
queuectl list
# Filter by state
queuectl list --state pending
queuectl list --state completed
queuectl list --state failedOutput:
ββββββββββββββ³βββββββββββββββββββββ³ββββββββββββ³ββββββββββββ³βββββββββββββββ
β ID β Command β State β Retries β Created At β
β‘βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β 5f07c123 β echo 'Test Job' β pending β 0/3 β 2025-01-15 β
ββββββββββββββ΄βββββββββββββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββββββ
# Start 2 worker processes
queuectl worker start --count 2Output:
[Manager PID 1234] Starting 2 workers...
[Worker PID 5678] Loop started
[Executor] Running job 5f07c123...
[Executor] Job completed successfully.
Stop Workers:
# Graceful shutdown (Ctrl+C or send SIGTERM)
^C
[Worker PID 5678] Received shutdown signal, finishing current job...
[Worker PID 5678] Shutdown complete.# View all failed jobs in DLQ
queuectl dlq list
# Retry a specific job from DLQ
queuectl dlq retry <job_id>
# Clear all jobs from DLQ
queuectl dlq clear# Set configuration values
queuectl config set max-retries 5
queuectl config set worker-count 4
# Get a specific config value
queuectl config get max-retries
# List all configuration
queuectl config listOutput:
Current configuration:
max-retries: 5
worker-count: 4
ββββββββββββββββββββββββββββββββ
β CLI Layer β
β (Typer + Rich interface) β
β------------------------------β
β β’ queuectl enqueue/list β
β β’ queuectl worker start β
β β’ queuectl dlq/config β
ββββββββββββββββ¬ββββββββββββββββ
β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββ
β β β
βΌ βΌ βΌ
ββββββββββββββββββββββ βββββββββββββββββββββββββ ββββββββββββββββββββββββ
β Repository Layer β β Worker Management β β Config Layer β
β (JobRepository, β β (manager.py) β β (config.py) β
β ConfigRepo) β β-----------------------β β----------------------β
β--------------------β β β’ Spawns processes β β β’ Key-value config β
β β’ SQLite queries β β β’ Graceful shutdown β β β’ CLI-based updates β
β β’ Job persistence β β β’ Process isolation β β β’ Persists to DB β
ββββββββββββ¬ββββββββββ ββββββββββββββ¬βββββββββββ ββββββββββββ¬βββββββββββ
β β β
β β β
βΌ βΌ βΌ
ββββββββββββββββββββββ ββββββββββββββββββββββ ββββββββββββββββββββββ
β Worker Execution β β Retry & DLQ Logic β β Database Layer β
β (workLoop, executorβ β (retry.py) β β (SQLite + Volume) β
β jobLifeCycle) β β--------------------β β--------------------β
β--------------------β β β’ Exponential back β β β’ jobs table β
β β’ Runs shell cmds β β β’ DLQ transition β β β’ config table β
β β’ Updates job stateβ β β’ Attempts trackingβ β β’ Persistent volumeβ
β β’ Manages retries β ββββββββββββββββββββββ ββββββββββββββββββββββ
ββββββββββββββββββββββ
| Component | Description |
|---|---|
| CLI Layer | Command interface for managing jobs, workers, config, and DLQ using Typer and Rich |
| Repository Layer | Handles job creation, listing, and database operations through JobRepository |
| Worker Management | Spawns and manages worker processes with graceful shutdown capabilities |
| Config Layer | Key-value configuration system with CLI-based updates persisted to database |
| Worker Execution | Runs shell commands, updates job states, and manages the execution lifecycle |
| Retry & DLQ Logic | Implements exponential backoff and transitions failed jobs to Dead Letter Queue |
| Database Layer | SQLite-based persistence for jobs and config with Docker volume support |
pending β processing β completed
β β
β failed β retry (pending)
β
βββ> dead (DLQ after max retries)
Each job moves through these states based on worker execution results.
- Jobs are stored in
queuectl.db(SQLite) - In Docker, this file lives inside
/app/data(mounted viaqueuectl-datavolume) - Configuration settings are persisted in the same database
- Ensures your queue survives application and container restarts
| Design Decision | Rationale |
|---|---|
| β SQLite | Simple, embedded database β ideal for local or small-scale deployments |
| βοΈ One command per job | Designed for shell-style tasks; keeps job model simple |
| π Exponential backoff | Prevents overwhelming systems during transient failures |
| π§ Single-node design | No distributed locking (but could be extended with PostgreSQL or Redis) |
| π§© Multiprocess workers | Scalable on one machine; not yet distributed/clustered |
| πΎ Minimal dependencies | Pure Python standard libs + Typer + Rich for portability |
# Install test dependencies
pip install pytest
# Run all tests
pytest -v
# Run specific test file
pytest tests/test_jobs.py -v
# Run with coverage
pytest --cov=queuectl tests/Expected Output:
tests/test_config.py::test_set_and_get_config PASSED
tests/test_dlq.py::test_dlq_job_state PASSED
tests/test_jobs.py::test_enqueue_and_list_jobs PASSED
tests/test_workers.py::test_run_valid_job PASSED
| Test File | Purpose |
|---|---|
test_jobs.py |
Verifies enqueue & listing of jobs |
test_workers.py |
Ensures workers execute commands correctly |
test_dlq.py |
Confirms failed jobs move to DLQ |
test_config.py |
Validates configuration persistence |
queuectl/
βββ cli/
β βββ main.py # Main CLI entry point
β βββ job_cli.py # Job management commands
β βββ worker_cli.py # Worker control commands
β βββ dlq_cli.py # Dead Letter Queue commands
β βββ config_cli.py # Configuration commands
βββ worker/
β βββ manager.py # Worker process manager
β βββ jobExecutor.py # Job execution logic
β βββ jobLifeCycle.py # State transitions
β βββ retry.py # Retry logic & backoff
β βββ workLoop.py # Main worker loop
β βββ shutdown.py # Graceful shutdown handler
βββ repository.py # Database operations
βββ config.py # Configuration management
βββ dbConnection.py # SQLite connection handler
βββ tests/
β βββ test_config.py
β βββ test_dlq.py
β βββ test_jobs.py
β βββ test_workers.py
βββ Dockerfile
βββ docker-compose.yml
βββ setup.py
βββ requirements.txt
βββ README.md
MIT License Β© 2025 β QueueCTL Project
This project is licensed under the MIT License. See the LICENSE file for details.
Developed by Suhas
π§ 3suhashs@gamil.com
π GitHub: Suhas-30
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
- Add support for job priorities
- Implement job dependencies (DAG execution)
- Add web UI for queue monitoring
- Support for PostgreSQL backend
- Distributed worker support with Redis
- Webhook notifications for job completion
- Scheduled/cron-style job execution
β If you find this project useful, please consider giving it a star on GitHub!