import { createLogger } from '@sim/logger' import { getErrorMessage } from '@sim/utils/errors' import { generateShortId } from '@sim/utils/id' import { type NextRequest, NextResponse } from 'next/server' import { webhookPollingContract } from '@/lib/api/contracts/webhooks' import { parseRequest } from '@/lib/api/server' import { verifyCronAuth } from '@/lib/auth/internal' import { acquireLock, releaseLock } from '@/lib/core/config/redis' import { runDetached } from '@/lib/core/utils/background' import { withRouteHandler } from '@/lib/core/utils/with-route-handler' import { pollProvider, VALID_POLLING_PROVIDERS } from '@/lib/webhooks/polling' const logger = createLogger('PollingAPI') /** Lock TTL in seconds — must match maxDuration so the lock auto-expires if the function times out. */ const LOCK_TTL_SECONDS = 180 export const dynamic = 'force-dynamic' export const maxDuration = 180 export const GET = withRouteHandler( async (request: NextRequest, context: { params: Promise<{ provider: string }> }) => { const requestId = generateShortId() let provider: string | undefined try { const authError = verifyCronAuth(request, 'webhook polling') if (authError) return authError const parsed = await parseRequest(webhookPollingContract, request, context) if (!parsed.success) return parsed.response provider = parsed.data.params.provider if (!VALID_POLLING_PROVIDERS.has(provider)) { return NextResponse.json( { error: `Unknown polling provider: ${provider}` }, { status: 404 } ) } const LOCK_KEY = `${provider}-polling-lock` const lockValue = requestId const locked = await acquireLock(LOCK_KEY, lockValue, LOCK_TTL_SECONDS) if (!locked) { return NextResponse.json( { success: true, message: 'Polling already in progress – skipped', requestId, status: 'skip', }, { status: 202 } ) } const pollingProvider = provider runDetached(`${pollingProvider}-polling`, async () => { try { await pollProvider(pollingProvider) } finally { await releaseLock(LOCK_KEY, lockValue).catch(() => {}) } }) return NextResponse.json( { success: true, message: `${provider} polling started`, requestId, status: 'started', }, { status: 202 } ) } catch (error) { const providerLabel = provider ?? 'webhook' logger.error(`Error during ${providerLabel} polling (${requestId}):`, error) return NextResponse.json( { success: false, message: `${providerLabel} polling failed`, error: getErrorMessage(error, 'Unknown error'), requestId, }, { status: 500 } ) } } )