// Remove expired share links. // // imagedrop's share_links rows carry an `expires_at` (ISO-8601 TEXT, written by // the client as `new Date(...).toISOString()`). The app already refuses to serve // an expired link, but the rows pile up forever (most of the table is expired). // A periodic cron sweep deletes the ones whose expiry has passed. // // runAs:'service' so the delete bypasses RLS (no per-row owner check needed). export const on = { type: 'cron', schedule: '*/30 * * * *', // every 30 minutes, UTC runAs: 'service', }; export default async function (ctx) { const now = Date.now(); // Same toISOString() format the client writes, so a lexicographic '<' on the // TEXT column is a chronological compare — the DB does the filtering, no // full-table scan. Each candidate is re-verified by parsing the date before // it is deleted (defence in depth for a destructive op). const nowIso = new Date(now).toISOString(); const rows = await ctx.db.from('share_links').lt('expires_at', nowIso).limit(2000).select(); if (!Array.isArray(rows)) return; let removed = 0; for (const row of rows) { const exp = Date.parse(row.expires_at); if (!Number.isFinite(exp) || exp >= now) continue; // skip anything not actually expired // .eq('id', …) targets the row by primary key for the DELETE. await ctx.db.from('share_links').eq('id', row.id).delete(); removed++; } if (removed > 0) console.log('expire-share-links: removed ' + removed + ' expired share link(s)'); }