/** * Edge Function Request Tracking Wrapper * * Wraps Supabase function invocations with request tracking for debugging and monitoring. * Provides correlation IDs for tracing requests across the system. */ import { supabase } from '@/integrations/supabase/client'; import { trackRequest } from './requestTracking'; import { getErrorMessage } from './errorHandler'; /** * Invoke a Supabase edge function with request tracking * * @param functionName - Name of the edge function to invoke * @param payload - Request payload * @param userId - User ID for tracking (optional) * @param parentRequestId - Parent request ID for chaining (optional) * @param traceId - Trace ID for distributed tracing (optional) * @returns Response data with requestId */ export async function invokeWithTracking( functionName: string, payload: Record = {}, userId?: string, parentRequestId?: string, traceId?: string ): Promise<{ data: T | null; error: any; requestId: string; duration: number }> { try { const { result, requestId, duration } = await trackRequest( { endpoint: `/functions/${functionName}`, method: 'POST', userId, parentRequestId, traceId, }, async (context) => { // Include client request ID in payload for correlation const { data, error } = await supabase.functions.invoke(functionName, { body: { ...payload, clientRequestId: context.requestId }, }); if (error) throw error; return data; } ); return { data: result, error: null, requestId, duration }; } catch (error: unknown) { const errorMessage = getErrorMessage(error); // On error, we don't have tracking info, so create basic response return { data: null, error: { message: errorMessage }, requestId: 'unknown', duration: 0, }; } } /** * Invoke multiple edge functions in parallel with batch tracking * * Uses a shared trace ID to correlate all operations. * * @param operations - Array of function invocation configurations * @param userId - User ID for tracking * @returns Array of results with their request IDs */ export async function invokeBatchWithTracking( operations: Array<{ functionName: string; payload: Record; }>, userId?: string ): Promise< Array<{ functionName: string; data: T | null; error: any; requestId: string; duration: number; }> > { const traceId = crypto.randomUUID(); const results = await Promise.allSettled( operations.map(async (op) => { const result = await invokeWithTracking( op.functionName, op.payload, userId, undefined, traceId ); return { functionName: op.functionName, ...result }; }) ); return results.map((result, index) => { if (result.status === 'fulfilled') { return result.value; } else { return { functionName: operations[index].functionName, data: null, error: { message: result.reason?.message || 'Unknown error' }, requestId: 'unknown', duration: 0, }; } }); }