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:
RhenCloud 2026-08-17 15:01:20 +08:00
parent 2e1b0f022e
commit 25ebae4ae5
No known key found for this signature in database
GPG key ID: A574A617378C4E0B
46 changed files with 1450 additions and 117 deletions

View file

@ -2,6 +2,7 @@ import type { Env, Group, GroupMember, GroupRole } from "../types";
import { isAdminUser } from "./session";
import { log } from "../lib/log";
import { migrateGroups, validateGroups } from "../config/schema";
import { getConfigStore } from "../config";
const GROUPS_KEY = "config:groups";
const GROUPS_CACHE_TTL = 300_000;
@ -40,6 +41,9 @@ export function normalizeGroupMembers(group: Group): GroupMember[] {
}
export async function loadGroups(kv: KVNamespace): Promise<Group[]> {
const store = getConfigStore(kv);
if (store) return store.loadGroups();
if (groupsCache && Date.now() < groupsCache.expiresAt) {
return groupsCache.groups;
}
@ -55,6 +59,12 @@ export async function loadGroups(kv: KVNamespace): Promise<Group[]> {
}
export async function saveGroups(kv: KVNamespace, groups: Group[]): Promise<void> {
const store = getConfigStore(kv);
if (store) {
await store.saveGroups(groups);
groupsCache = null;
return;
}
await kv.put(GROUPS_KEY, JSON.stringify(groups));
groupsCache = null;
}