Files
wehub-resource-sync d25d482dc2
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:20:55 +08:00

89 lines
2.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 }
)
}
}
)