${serviceName}: ${message}
`, + }); + logger.info('alertService.sendAlertEmail: sent', { serviceName, alertType, recipient }); + } catch (err) { + logger.error('alertService.sendAlertEmail: failed', { + error: err instanceof Error ? err.message : String(err), + serviceName, alertType, + }); + // Do NOT re-throw — email failure should not break the probe run + } +} +``` + +### Pattern 4: Fire-and-Forget Analytics (ANLY-03) + +**What:** `analyticsService.recordProcessingEvent()` uses `void` (no `await`) so the Supabase write is completely detached from the processing pipeline. The function signature returns `void` to make it impossible to accidentally `await` it. + +**Critical rule:** The function MUST be called with `void` or not awaited anywhere it's used. TypeScript enforcing `void` return type ensures this. + +```typescript +// Source: PITFALL-6 pattern — fire-and-forget is mandatory +export interface ProcessingEventData { + document_id: string; + user_id: string; + event_type: 'upload_started' | 'processing_started' | 'completed' | 'failed'; + duration_ms?: number; + error_message?: string; + stage?: string; +} + +// Return type is void (not Promise