JoSch is a memory-bound, resilient background job scheduling engine written from scratch in Go. It operates without an external database, utilizing an in-memory storage layer backed by a custom Write-Ahead Log (WAL) to guarantee durability and crash recovery.
To protect system throughput, incoming jobs are routed immediately based on their execution timestamp:
-
Immediate Lane (
$O(1)$ Pass-Through): Jobs requiring instant execution bypass the priority heap entirely and are dropped straight into an un-sorted channel (immediateCh). This prevents heavy heap-rebalancing taxes under intense immediate traffic. -
Delayed Lane (
$O(\log N)$ Min-Heap): Time-sensitive tasks are pushed to a thread-safe min-heap, maintaining strict execution order based on priority/time. -
Unified Worker Pool: Both lanes funnel into a single, bounded worker channel (
JobChannel). This guarantees absolute control over resource consumption (CPU/DB connections) and enforces a predictable memory ceiling.
The background orchestrator uses a non-polling, resource-efficient state machine:
- It locks and peeks at the top element of the min-heap to compute the sleep duration.
- It drops its lock and utilizes a persistent
time.Timerwithin a multiplexingselectblock to sleep efficiently. - The loop stays alert to native Go channel communication: incoming immediate jobs or higher-priority ready signals instantly interrupt the timer sleep, forcing a dynamic state re-evaluation without wasting CPU cycles.
Since the engine operates in-memory, state durability is achieved via an append-only JSON Lines (JSONL) Write-Ahead Log:
- Atomic State Transitions: System modifications flush sequentially to disk (
os.O_APPEND) at three core boundaries:SCHEDULED,IN_PROCESS, andCOMPLETED/FAILED. - Blueprint Reconstruction on Boot: On startup, the system parses the WAL file linearly from line 1 to EOF, aggregating records into an isolated tracking map.
SCHEDULEDadds a job;COMPLETED/FAILEDdeletes it. Active queues are populated only after the file stream ends, completely removing the need for a live database LSN pointer and preventing race conditions during recovery. - Atomic Log Compaction: To mitigate unbounded file growth, a compaction routine takes a snapshot of currently alive in-memory tasks, marshals them into a temporary file (
app.wal.tmp), and uses an atomicos.Rename()operation to replace the bloated historical log safely.