mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
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
This commit is contained in:
parent
2e1b0f022e
commit
25ebae4ae5
46 changed files with 1450 additions and 117 deletions
40
server/tasks/storage-prune.ts
Normal file
40
server/tasks/storage-prune.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
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" };
|
||||
}
|
||||
},
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue