import type { CounterKind, Totals } from "./counters-do";
type Row = { key: string; a: number; b: number; c: number };
type CounterStub = {
add(kind: CounterKind, scope: string, key: string, delta: Totals, meta: string | null): Promise<Totals>;
};
/**
* Adds what each flushed row gained since its last flush (its `base_*` columns) to a platform total in another
* Counters object, per key. Best effort: a lost forward only skews a platform safety net, never a bill.
*/
export async function forwardFlushed(
sql: SqlStorage,
namespace: DurableObjectNamespace,
target: { kind: CounterKind; scope: string },
rows: Row[],
): Promise<void> {
const deltas = rows.flatMap((row) => {
const base = sql
.exec<{ base_a: number | null; base_b: number | null; base_c: number | null }>(
"SELECT base_a, base_b, base_c FROM counters WHERE key = ?",
row.key,
)
.toArray()[0];
const delta: Totals = [row.a - (base?.base_a ?? 0), row.b - (base?.base_b ?? 0), row.c - (base?.base_c ?? 0)];
return delta.some((value) => value !== 0) ? [{ key: row.key, delta }] : [];
});
if (deltas.length === 0) return;
const stub = namespace.get(namespace.idFromName(`${target.kind}:${target.scope}`)) as unknown as CounterStub;
await Promise.all(
deltas.map(({ key, delta }) =>
stub
.add(target.kind, target.scope, key, delta, null)
.catch((error: unknown) => console.warn("Counter forward failed", target, key, error)),
),
);
}