Improve moderation edge flow and timeout handling

- Add early logging and health check to process-selective-approval edge function
- Implement idempotency check with timeout to avoid edge timeouts
- Expose health endpoint for connectivity diagnostics
- Increase client moderation action timeout from 30s to 60s
- Update moderation actions hook to accommodate longer timeouts
This commit is contained in:
gpt-engineer-app[bot]
2025-11-12 13:15:54 +00:00
parent 09c320f508
commit d18632c2b2
2 changed files with 59 additions and 5 deletions

View File

@@ -16,11 +16,42 @@ import { ValidationError } from '../_shared/typeValidation.ts';
const handler = async (req: Request, context: { supabase: any; user: any; span: any; requestId: string }) => {
const { supabase, user, span: rootSpan, requestId } = context;
// Early logging - confirms request reached handler
addSpanEvent(rootSpan, 'handler_entry', {
requestId,
userId: user.id,
timestamp: Date.now()
});
setSpanAttributes(rootSpan, {
'user.id': user.id,
'function.name': 'process-selective-approval'
});
// Health check endpoint
if (req.url.includes('/health')) {
addSpanEvent(rootSpan, 'health_check_start');
const { data, error } = await supabase
.from('content_submissions')
.select('count')
.limit(1);
addSpanEvent(rootSpan, 'health_check_complete', {
dbConnected: !error,
error: error?.message
});
return new Response(JSON.stringify({
status: 'ok',
dbConnected: !error,
timestamp: Date.now(),
error: error?.message
}), {
headers: { 'Content-Type': 'application/json' },
status: error ? 500 : 200
});
}
// STEP 1: Parse and validate request
addSpanEvent(rootSpan, 'validation_start');
@@ -57,14 +88,37 @@ const handler = async (req: Request, context: { supabase: any; user: any; span:
});
addSpanEvent(rootSpan, 'validation_complete');
// STEP 2: Idempotency check
// STEP 2: Idempotency check with timeout
addSpanEvent(rootSpan, 'idempotency_check_start');
const { data: existingKey } = await supabase
const idempotencyCheckPromise = supabase
.from('submission_idempotency_keys')
.select('*')
.eq('idempotency_key', idempotencyKey)
.single();
// Add 5 second timeout for idempotency check
const timeoutPromise = new Promise((_, reject) =>
setTimeout(() => reject(new Error('Idempotency check timed out after 5s')), 5000)
);
let existingKey;
try {
const result = await Promise.race([
idempotencyCheckPromise,
timeoutPromise
]) as any;
existingKey = result.data;
} catch (timeoutError: any) {
addSpanEvent(rootSpan, 'idempotency_check_timeout', { error: timeoutError.message });
throw new Error(`Database query timeout: ${timeoutError.message}`);
}
addSpanEvent(rootSpan, 'idempotency_check_complete', {
foundKey: !!existingKey,
status: existingKey?.status
});
if (existingKey?.status === 'completed') {
addSpanEvent(rootSpan, 'idempotency_cache_hit');
setSpanAttributes(rootSpan, { 'cache.hit': true });