feat(p9): IiosDlqItem + DlqService (dead-letter + deterministic replay)

Task D.1: mandated dlq_item table (sourceType/sourceId/failureStage/errorCode/
retryCount/payloadRef/consumerName/scopeId/status). DlqService.record (idempotent
per consumer+sourceId, bumps retryCount), onConsumerFailure (quarantine + clear the
IiosProcessedEvent claim so it's replayable — fixes claim-then-fail), registerHandler
+ replay (clears claim, awaits the registered consumer handler → RESOLVED on success,
QUARANTINED+retry on repeat throw; outbox-sourced items reset to PENDING). Wired into
OutboxModule; resetDb truncates it. 3 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-03 01:28:48 +05:30
parent e5d3ce5ecd
commit 208fb0b4f0
6 changed files with 219 additions and 3 deletions
@@ -8,7 +8,7 @@ import type { PrismaClient } from '@prisma/client';
export async function resetDb(prisma: PrismaClient): Promise<void> {
await prisma.$executeRawUnsafe(
`TRUNCATE TABLE
"IiosAuditLink",
"IiosDlqItem","IiosAuditLink",
"IiosMeetingActionItem","IiosActionItem","IiosTranscriptSegment","IiosMeetingTranscript","IiosMeetingSummary","IiosMeetingParticipant","IiosMeeting","IiosMeetingRequest",
"IiosCalendarSyncCursor","IiosCalendarEvent","IiosCalendarProviderAccount","IiosAvailabilityWindow",
"IiosAiEvidenceLink","IiosAiClaim","IiosAiToolCall","IiosAiArtifact","IiosAiModelRun","IiosAiJob","IiosEmbeddingRef",