Conversion job queue and pandoc sidecar integration #62
Labels
No Label
area:auth
area:docs
area:export
area:ops
area:storage
area:supply-chain
auth
backend
blocked
collab
deployment
docs
effort:L
effort:M
effort:S
frontend
plugins
qa
vs-nfd
vs-nfd:blocker
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: stwaidele/dorfteich#62
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Import/export conversions run asynchronously against internal sidecars with limits and graceful failure (ADR 0009).
Scope
Add
pandoc(server mode) to the Compose stack (internal network, pinned image, healthcheck); implement the conversion job flow on thejobstable: enqueue → worker calls sidecar with timeout (60 s) and size limit → store result/error →GET /jobs/:idpolling endpoint with job ownership check; typed client for pandoc-server in a dedicated service; failure modes (sidecar down, timeout, unsupported content) mapped to distinct localized errors.Acceptance criteria
Technical notes
jobs).Dependencies
Depends on #6, #31.
Size: ~1.5 days
Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add
deanden), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.#62 verifiziert & abgeschlossen — Conversion-Job-Queue + pandoc-Sidecar (ADR 0009).
Pipeline (
4755c18): alle 7 Kontexte grün — CI (Lint/Typecheck/Test, i18n:check, api-db 193), Auth-e2e, Build → Deploy-Test → Smoke → Promote-Int. Der Deploy lief sauber durch, obwohl die Stages den Sidecar noch nicht hatten: die api degradiert bei fehlendem pandoc auf warn-level (readyzconverter: warn, Instanz bleibt ready) — genau das zeigt der Smoke-Test-Durchlauf.Stage-Provisioning (Test + Int, VPS 188.245.116.44): neue
docker-compose.yml(mit pandoc-Service) in/home/DOCKER/dorfteich-{test,int}/eingespielt (Backup*.bak-pre62),docker compose pull pandoc && up -d.healthyauf beiden Stages (Compose-Healthcheckwget /version).converter: okauf Test und Int (vorherwarn (fetch failed)→ Beweis für die warn-level-Degradation).dorfteich-test-api-1→http://pandoc:3030/konvertiert markdown→html (korrektes HTML) und markdown→docx (gültige PK/OOXML-Bytes, 9925 B) — derselbe Pfad, den der Worker nutzt.Umfang:
pandoc/core:3.6(server mode) im internen Netz, gepinnt, Healthcheck; apidepends_onpandoc + neue EnvPANDOC_URL(defaulthttp://pandoc:3030). readyzconverter-Check (warn-level, nie unready).ConversionJob-Tabelle (Per-Request-Queue, getrennt von der name-keyed Maintenance-Job-Tabelle): owner, Formate, input/result-Bytes, status, attempts, lockedAt.PandocServerConverter: POST/mit{text,from,to,standalone}, Binär-Input-Formate (docx/odt) base64 imtext, 60s-Timeout (AbortController), Input/Output-Size-Caps; Fehler →converter_unavailable/converter_timeout(retryable) vsconversion_failed(final).ConversionWorker: claimt je einen Job viaFOR UPDATE SKIP LOCKED(safe gegen überlappende Sweeps + 2. Prozess), Stale-Lock-Recovery, retry-then-fail (3 Versuche); 2s-Sweep + wake-on-enqueue → überlebt API-Neustart.ConversionJobService.enqueue(size-limited) + owner-scopedGET /jobs/:id(Poll) +GET /jobs/:id/result(Stream); fremd/unbekannt → 404.Akzeptanzkriterien:
converter_timeout).Tests:
conversion-job.e2e.db.test.ts(Fake-Converter via neuencreateTestApp-Override-Hook: enqueue→convert→poll→result, fremd/unbekannt 404, Restart-Survival, sidecar-down-fails-after-retries+API-healthy) +pandoc.converter.test.ts(success, non-200→conversion_failed, refused→converter_unavailable, delay→converter_timeout). Lokal zusätzlich gegen echtespandoc/core:3.6verifiziert (markdown→docx, docx→markdown-Roundtrip). api 193 (+9), shared 121, web 50 grün.Nächste M6-Issues bauen darauf auf: #63 (Import docx/odt) + #65 (Export) enqueuen Jobs auf dieser Queue.