mirror of
https://github.com/juherr/kill-the-news.git
synced 2026-06-20 22:03:48 +00:00
feat(stats): count emails forwarded to the catch-all fallback
Adds an emails_forwarded counter (a subset of emails_rejected) bumped on a successful FALLBACK_FORWARD_ADDRESS forward. Dropped = rejected − forwarded. Surfaced in the /api/v1/stats response and the public status page. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import { describe, it, expect, beforeEach } from "vitest";
|
||||
import "../test/setup";
|
||||
import { createMockEnv } from "../test/setup";
|
||||
import { handleCloudflareEmail } from "./cloudflare-email";
|
||||
import { getCounters } from "../application/stats";
|
||||
|
||||
const VALID_FEED_ID = "apple.mountain.42";
|
||||
const DOMAIN = "test.getmynews.app";
|
||||
@@ -245,5 +246,53 @@ describe("handleCloudflareEmail", () => {
|
||||
),
|
||||
).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("increments the emails_forwarded counter on a successful forward", async () => {
|
||||
const { forward } = spyForward();
|
||||
env.FALLBACK_FORWARD_ADDRESS = FALLBACK;
|
||||
|
||||
await handleCloudflareEmail(
|
||||
makeMessage({ forward }),
|
||||
env as any,
|
||||
{ waitUntil: () => {} } as any,
|
||||
);
|
||||
|
||||
const counters = await getCounters(env.EMAIL_STORAGE as any);
|
||||
expect(counters.emails_forwarded).toBe(1);
|
||||
});
|
||||
|
||||
it("does not increment emails_forwarded when the forward fails", async () => {
|
||||
env.FALLBACK_FORWARD_ADDRESS = FALLBACK;
|
||||
const forward = async () => {
|
||||
throw new Error("destination address not verified");
|
||||
};
|
||||
|
||||
await handleCloudflareEmail(
|
||||
makeMessage({ forward }),
|
||||
env as any,
|
||||
{ waitUntil: () => {} } as any,
|
||||
);
|
||||
|
||||
const counters = await getCounters(env.EMAIL_STORAGE as any);
|
||||
expect(counters.emails_forwarded).toBe(0);
|
||||
});
|
||||
|
||||
it("does not increment emails_forwarded for dropped reasons", async () => {
|
||||
const { forward } = spyForward();
|
||||
env.FALLBACK_FORWARD_ADDRESS = FALLBACK;
|
||||
await env.EMAIL_STORAGE.put(
|
||||
`feed:${VALID_FEED_ID}:config`,
|
||||
JSON.stringify({ expires_at: Date.now() - 1000 }),
|
||||
);
|
||||
|
||||
await handleCloudflareEmail(
|
||||
makeMessage({ forward }),
|
||||
env as any,
|
||||
{ waitUntil: () => {} } as any,
|
||||
);
|
||||
|
||||
const counters = await getCounters(env.EMAIL_STORAGE as any);
|
||||
expect(counters.emails_forwarded).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
RawAttachment,
|
||||
IngestRejectionReason,
|
||||
} from "../application/email-processor";
|
||||
import { bumpCounters } from "../application/stats";
|
||||
import { normalizeCid } from "../infrastructure/html-processor";
|
||||
import { logger } from "./logger";
|
||||
|
||||
@@ -80,6 +81,9 @@ async function maybeForwardFallback(
|
||||
|
||||
try {
|
||||
await message.forward(fallback);
|
||||
// Counted as a subset of emails_rejected (already bumped in processEmail);
|
||||
// the dropped count is derived as emails_rejected − emails_forwarded.
|
||||
await bumpCounters(env.EMAIL_STORAGE, { emails_forwarded: 1 });
|
||||
} catch (error) {
|
||||
logger.warn("Fallback forward failed", {
|
||||
to: message.to,
|
||||
|
||||
@@ -14,6 +14,7 @@ describe("CountersRepository", () => {
|
||||
feeds_deleted: 0,
|
||||
emails_received: 2,
|
||||
emails_rejected: 0,
|
||||
emails_forwarded: 0,
|
||||
unsubscribes_sent: 0,
|
||||
});
|
||||
expect(await repo.getRaw()).toMatchObject({ emails_received: 2 });
|
||||
|
||||
Reference in New Issue
Block a user