${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