mirror your GitHub repos to tangled.org automatically
1

Configure Feed

Select the types of activity you want to include in your feed.

at main 1.8 kB View raw
1import crypto from 'node:crypto' 2import { dispatch } from '#server/utils/job-handlers' 3import { claim, complete, fail } from '#server/utils/queue' 4 5const LEASE_MS = 5 * 60_000 // 5 min — generous for a sync job 6const DEFAULT_BUDGET_MS = 25_000 // leave headroom under Vercel's 10s default; pro tiers can override 7 8export default defineEventHandler(async event => { 9 const cronSecret = process.env.CRON_SECRET 10 if (!cronSecret) { 11 throw createError({ statusCode: 500, statusMessage: 'cron secret not configured' }) 12 } 13 14 const auth = getRequestHeader(event, 'authorization') 15 if (auth !== `Bearer ${cronSecret}`) { 16 throw createError({ statusCode: 401, statusMessage: 'unauthorized' }) 17 } 18 19 const workerId = `${process.env.VERCEL_DEPLOYMENT_ID ?? 'local'}:${crypto.randomUUID()}` 20 const budgetMs = Number(useRuntimeConfig().workerBudgetMs) || DEFAULT_BUDGET_MS 21 const deadline = Date.now() + budgetMs 22 23 let processed = 0 24 let drained = false 25 26 // Sequential by design: each iteration claims one job, runs it, records the 27 // outcome. We don't parallelise because each Vercel invocation is a single 28 // small worker; concurrency comes from cron firing multiple invocations. 29 // eslint-disable-next-line no-await-in-loop 30 while (Date.now() < deadline) { 31 // eslint-disable-next-line no-await-in-loop 32 const job = await claim(workerId, LEASE_MS) 33 if (!job) { 34 drained = true 35 break 36 } 37 38 try { 39 // eslint-disable-next-line no-await-in-loop 40 await dispatch(job) 41 // eslint-disable-next-line no-await-in-loop 42 await complete(job.id) 43 } 44 catch (err) { 45 // eslint-disable-next-line no-await-in-loop 46 await fail(job.id, job.attempts, err) 47 } 48 49 processed++ 50 } 51 52 return { ok: true, processed, drained, workerId } 53})