mirror your GitHub repos to tangled.org automatically
1

Configure Feed

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

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 config = useRuntimeConfig() 10 const cronSecret = config.cronSecret 11 if (!cronSecret) { 12 throw createError({ statusCode: 500, statusMessage: 'cron secret not configured' }) 13 } 14 15 const auth = getRequestHeader(event, 'authorization') 16 if (auth !== `Bearer ${cronSecret}`) { 17 throw createError({ statusCode: 401, statusMessage: 'unauthorized' }) 18 } 19 20 const workerId = `${process.env.VERCEL_DEPLOYMENT_ID ?? 'local'}:${crypto.randomUUID()}` 21 const budgetMs = Number(config.workerBudgetMs) || DEFAULT_BUDGET_MS 22 const deadline = Date.now() + budgetMs 23 24 let processed = 0 25 let drained = false 26 27 // Sequential by design: each iteration claims one job, runs it, records the 28 // outcome. We don't parallelise because each Vercel invocation is a single 29 // small worker; concurrency comes from cron firing multiple invocations. 30 // eslint-disable-next-line no-await-in-loop 31 while (Date.now() < deadline) { 32 // eslint-disable-next-line no-await-in-loop 33 const job = await claim(workerId, LEASE_MS) 34 if (!job) { 35 drained = true 36 break 37 } 38 39 try { 40 // eslint-disable-next-line no-await-in-loop 41 await dispatch(job) 42 // eslint-disable-next-line no-await-in-loop 43 await complete(job.id) 44 } 45 catch (err) { 46 // eslint-disable-next-line no-await-in-loop 47 await fail(job.id, job.attempts, err) 48 } 49 50 processed++ 51 } 52 53 return { ok: true, processed, drained, workerId } 54})