Postgres-Jobqueue (processing_jobs, FOR UPDATE SKIP LOCKED), In-Prozess- Worker-Goroutinen, kein Redis/AMQP. Enqueue mit Idempotency-Key-Dedup, Dequeue mit Stale-Lock-Wiedervorlage (Absturzsicherheit), Fail mit arithmetischem Backoff und Dead-Letter-Queue nach erschoepften Versuchen, RequeueDeadLetter fuer manuelle Wiederholung. Auf 192.168.1.131 verifiziert: Absturz-Wiedervorlage (Job von einem "abgestuerzten" Worker nie completed/failed, zweiter Worker holt ihn nach Ablauf der Sperre erneut), Idempotenz bei Doppelzustellung (gleicher idempotency_key erzeugt nur 1 Zeile), DLQ-Eintrag manuell wiederholbar. Vier reale Fehler beim Testen gefunden und behoben: zwei pgx-Typinferenz- Bugs im SQL-Parameterhandling (toter workerID-Parameter ohne Referenz in der Query; untypisiertes any statt []string fuer den ::text[]-Cast), sowie zwei Testinfrastruktur-Bugs (dms_tenant_test sammelte schema_migrations- Zustand ueber Sitzungen hinweg an, jobqueue-Testfixture raeumte processing_jobs nicht auf) - neues scripts/reset-test-env.sh + make check (-p 1) analog Core behoben. Siehe dms/docs/FDN-04-PRUEFPROTOKOLL.md fuer alle Pruefungsergebnisse. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HhgFcLS8tYMhDJpP74C6AQ
31 lines
1.6 KiB
SQL
31 lines
1.6 KiB
SQL
-- FDN-04: Postgres-Jobqueue fuer asynchrone Verarbeitung (OCR, Konvertierung,
|
|
-- Indexierung, Exporte) — kein Redis/AMQP, dasselbe Muster wie das
|
|
-- projektweite Postgres-Jobqueue-Konzept (siehe SKALIERUNGSKONZEPT.md).
|
|
-- Laeuft in der DB EINES Mandanten (Modell C, siehe Core TEN-01).
|
|
CREATE TABLE processing_jobs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
job_type TEXT NOT NULL,
|
|
payload JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
-- idempotency_key verhindert doppelte Einreihung DERSELBEN logischen
|
|
-- Aufgabe (z.B. "ocr:<revision_id>") — NULL erlaubt mehrere Zeilen ohne
|
|
-- Dedup-Anspruch (Standard-Postgres-Verhalten: NULL ist nie gleich NULL
|
|
-- im UNIQUE-Index).
|
|
idempotency_key TEXT UNIQUE,
|
|
status TEXT NOT NULL DEFAULT 'pending'
|
|
CHECK (status IN ('pending', 'processing', 'succeeded', 'failed', 'dead_letter')),
|
|
attempts INT NOT NULL DEFAULT 0,
|
|
max_attempts INT NOT NULL DEFAULT 5,
|
|
available_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
locked_at TIMESTAMPTZ,
|
|
locked_by TEXT,
|
|
last_error TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
-- Deckt genau die Zugriffsmuster von Dequeue (status+available_at) und der
|
|
-- Stale-Lock-Wiedervorlage (status+locked_at) ab.
|
|
CREATE INDEX idx_processing_jobs_pending ON processing_jobs (available_at) WHERE status = 'pending';
|
|
CREATE INDEX idx_processing_jobs_processing ON processing_jobs (locked_at) WHERE status = 'processing';
|
|
CREATE INDEX idx_processing_jobs_job_type ON processing_jobs (job_type);
|