| 123456789101112131415161718192021222324252627282930313233343536 |
- // 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)');
- }
|