WebHooker/server/tasks/storage-prune.ts
RhenCloud 25ebae4ae5
feat(storage): migrate config, dedup and delivery state to D1
- Move oversized queue payloads from KV to R2 (PAYLOAD binding, webhooks/YYYY/MM/DD/*.json, KV queue:payload:* fallback)
- Persist routes/groups to D1 (d1_routes/d1_groups) with memory -> KV -> D1 three-tier cache, seeded from legacy KV config keys
- Move webhook dedup (dedup_keys), delivery state (delivery_state) and message tracking (message_tracking) to D1 via canUseD1 probe with automatic KV fallback
- Batch send_logs inserts (recordSendBatch) and add group_id/ts index
- Add storage-prune scheduled task for expired dedup/state/tracking rows
- Add TTL to invite:group:{id} index and audit all ephemeral KV keys
- Add D1 indexes for the new tables
- Sync AGENTS.md, README.md/zh and docs/ (en/zh) with the new storage layout
2026-08-17 15:01:20 +08:00

40 lines
No EOL
1.5 KiB
TypeScript

import { cfEnv } from "../lib/cf";
import { log } from "../lib/lib/log";
const DELIVERY_STATE_RETENTION_MS = 7 * 24 * 3600 * 1000;
const MESSAGE_TRACKING_RETENTION_MS = 30 * 24 * 3600 * 1000;
/**
* Scheduled: purge expired rows from the D1-backed ephemeral stores
* (dedup_keys, delivery_state, message_tracking). These replaced the KV keys
* that relied on per-entry TTL; D1 rows must be removed by this task instead.
*/
export default defineTask({
meta: { name: "storage:prune", description: "Prune D1 dedup/delivery/message-tracking rows" },
async run(event) {
try {
const env = cfEnv(event);
const now = Date.now();
let removed = 0;
const dedup = await env.DB.prepare("DELETE FROM dedup_keys WHERE expires_at < ?")
.bind(now)
.run();
removed += dedup.meta?.changes ?? 0;
const delivery = await env.DB.prepare("DELETE FROM delivery_state WHERE updated_at < ?")
.bind(now - DELIVERY_STATE_RETENTION_MS)
.run();
removed += delivery.meta?.changes ?? 0;
const messages = await env.DB.prepare(
"DELETE FROM message_tracking WHERE updated_at < ?",
)
.bind(now - MESSAGE_TRACKING_RETENTION_MS)
.run();
removed += messages.meta?.changes ?? 0;
if (removed > 0) log.info({ removed }, "Pruned D1 storage rows");
return { result: "ok", removed };
} catch (err) {
log.error({ err }, "Storage prune from cron failed");
return { result: "error" };
}
},
});