docs: add readme architecture diagrams
This commit is contained in:
83
README.md
83
README.md
@@ -1,4 +1,4 @@
|
||||
# Minimal Senior-Level Job Queue
|
||||
# Job Queue
|
||||
|
||||
This is a deliberately small PostgreSQL-backed job queue for the interview assignment.
|
||||
|
||||
@@ -14,6 +14,41 @@ The important parts are:
|
||||
- idempotent job creation
|
||||
- demo UI with job state and event polling
|
||||
|
||||
## Architecture
|
||||
|
||||

|
||||
|
||||
|
||||
There is no queue table and no worker table. Workers are ephemeral process threads with generated ids. The queue is internal and ordered by:
|
||||
|
||||
```text
|
||||
priority DESC, available_at ASC, created_at ASC, id ASC
|
||||
```
|
||||
|
||||
## Statuses
|
||||
|
||||

|
||||
|
||||
The database also validates row shape:
|
||||
|
||||
- queued jobs cannot have locks or finish timestamps
|
||||
- running jobs must have a lock owner and lease deadline
|
||||
- terminal jobs must have a finish timestamp and no lock
|
||||
|
||||
## At-Least-Once Execution
|
||||
|
||||

|
||||
|
||||
This queue provides at-least-once execution, not exactly-once execution.
|
||||
|
||||
A worker can perform an external side effect and crash before marking a job succeeded. The lease will expire and the job can run again. Real handlers should therefore be idempotent.
|
||||
|
||||
## Why PostgreSQL
|
||||
|
||||
The assignment requires PostgreSQL, and PostgreSQL gives a compact solution for safe concurrent claiming through `SELECT ... FOR UPDATE SKIP LOCKED`. This keeps the implementation transactional, inspectable, and easy to demo.
|
||||
|
||||
For a high-throughput distributed production queue, Redis-backed systems such as BullMQ or Sidekiq-style designs are common. That is documented as the next architecture, not implemented here.
|
||||
|
||||
## Run
|
||||
|
||||
```powershell
|
||||
@@ -60,52 +95,6 @@ docker compose up -d --build worker
|
||||
docker compose logs -f worker
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```text
|
||||
React UI
|
||||
|
|
||||
Django API ---- PostgreSQL
|
||||
|
|
||||
Django worker process
|
||||
|
|
||||
N worker threads from env
|
||||
```
|
||||
|
||||
There is no queue table and no worker table. Workers are ephemeral process threads with generated ids. The queue is internal and ordered by:
|
||||
|
||||
```text
|
||||
priority DESC, available_at ASC, created_at ASC, id ASC
|
||||
```
|
||||
|
||||
## Statuses
|
||||
|
||||
```text
|
||||
queued -> running
|
||||
running -> succeeded
|
||||
running -> queued retry after failure or timeout
|
||||
running -> failed attempts exhausted
|
||||
failed -> queued manual retry
|
||||
```
|
||||
|
||||
The database also validates row shape:
|
||||
|
||||
- queued jobs cannot have locks or finish timestamps
|
||||
- running jobs must have a lock owner and lease deadline
|
||||
- terminal jobs must have a finish timestamp and no lock
|
||||
|
||||
## At-Least-Once Execution
|
||||
|
||||
This queue provides at-least-once execution, not exactly-once execution.
|
||||
|
||||
A worker can perform an external side effect and crash before marking a job succeeded. The lease will expire and the job can run again. Real handlers should therefore be idempotent.
|
||||
|
||||
## Why PostgreSQL
|
||||
|
||||
The assignment requires PostgreSQL, and PostgreSQL gives a compact solution for safe concurrent claiming through `SELECT ... FOR UPDATE SKIP LOCKED`. This keeps the implementation transactional, inspectable, and easy to demo.
|
||||
|
||||
For a high-throughput distributed production queue, Redis-backed systems such as BullMQ or Sidekiq-style designs are common. That is documented as the next architecture, not implemented here.
|
||||
|
||||
## Useful Commands
|
||||
|
||||
Run backend tests locally with SQLite fallback:
|
||||
|
||||
Reference in New Issue
Block a user