refactor(domain): split Icon/WebSub/Counters out of FeedRepository
FeedRepository no longer owns favicons, WebSub subscriber lists or the monitoring counters singleton. Each concern gets its own repository (IconRepository, WebSubSubscriptionRepository, CountersRepository), sharing the key schema via feed-keys. KV key strings are unchanged; counters increment policy stays in utils/stats.ts. Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
b347f2f625
commit
a31ff42f59
13 files changed
+204
-119
No files matched your search
@@ -1,14 +1,12 @@
|
||||
import {
|
||||
Counters,
|
||||
EmailData,
|
||||
Env,
|
||||
FeedConfig,
|
||||
FeedList,
|
||||
FeedListItem,
|
||||
FeedMetadata,
|
||||
WebSubSubscription,
|
||||
} from "../types";
|
||||
import { FEEDS_LIST_KEY, STATS_KEY } from "../config/constants";
|
||||
import { FEEDS_LIST_KEY } from "../config/constants";
|
||||
import { feedKeys } from "./feed-keys";
|
||||
import { logger } from "../lib/logger";
|
||||
|
||||
@@ -37,15 +35,6 @@ export class FeedRepository {
|
||||
return feedKeys.metadata(feedId);
|
||||
}
|
||||
|
||||
/** KV key for a domain's cached favicon (shared across feeds). */
|
||||
iconKey(domain: string): string {
|
||||
return feedKeys.icon(domain);
|
||||
}
|
||||
|
||||
private websubKey(feedId: string): string {
|
||||
return feedKeys.websub(feedId);
|
||||
}
|
||||
|
||||
/** Prefix covering every key owned by a feed (config, metadata, emails). */
|
||||
feedKeyPrefix(feedId: string): string {
|
||||
return feedKeys.feedPrefix(feedId);
|
||||
@@ -241,55 +230,4 @@ export class FeedRepository {
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/** Number of feeds that currently hold at least one WebSub subscription. */
|
||||
countSubscriptionKeys(): Promise<number> {
|
||||
return this.countKeysByPrefix("websub:");
|
||||
}
|
||||
|
||||
// ── Monitoring counters ───────────────────────────────────────────────────
|
||||
|
||||
async getCountersRaw(): Promise<Counters | null> {
|
||||
return (await this.kv.get(STATS_KEY, { type: "json" })) as Counters | null;
|
||||
}
|
||||
|
||||
async putCounters(counters: Counters): Promise<void> {
|
||||
await this.kv.put(STATS_KEY, JSON.stringify(counters));
|
||||
}
|
||||
|
||||
// ── Favicons ──────────────────────────────────────────────────────────────
|
||||
|
||||
async getIconText(domain: string): Promise<string | null> {
|
||||
return this.kv.get(this.iconKey(domain), "text");
|
||||
}
|
||||
|
||||
async getIconJson<T>(domain: string): Promise<T | null> {
|
||||
return (await this.kv.get(this.iconKey(domain), {
|
||||
type: "json",
|
||||
})) as T | null;
|
||||
}
|
||||
|
||||
async putIcon(
|
||||
domain: string,
|
||||
value: string,
|
||||
ttlSeconds: number,
|
||||
): Promise<void> {
|
||||
await this.kv.put(this.iconKey(domain), value, {
|
||||
expirationTtl: ttlSeconds,
|
||||
});
|
||||
}
|
||||
|
||||
// ── WebSub subscriptions ──────────────────────────────────────────────────
|
||||
|
||||
async getSubscriptions(feedId: string): Promise<WebSubSubscription[]> {
|
||||
const raw = await this.kv.get(this.websubKey(feedId), "json");
|
||||
return (raw as WebSubSubscription[] | null) ?? [];
|
||||
}
|
||||
|
||||
async saveSubscriptions(
|
||||
feedId: string,
|
||||
subscriptions: WebSubSubscription[],
|
||||
): Promise<void> {
|
||||
await this.kv.put(this.websubKey(feedId), JSON.stringify(subscriptions));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user