Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions notification-service/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Notifier } from "./notifier";
import { createApi } from "./api";
import { pollScoreChanges, PollHandle } from "./listener";
import { ScoreChangedEvent } from "./types";
import { Metrics } from "./metrics";

/**
* Builds a signal handler that lets in-flight event processing finish and
Expand Down Expand Up @@ -39,10 +40,11 @@ async function main(): Promise<void> {
const config = loadConfig();

const store = new Store(config.db_path);
const notifier = new Notifier(config, store);
const metrics = new Metrics();
const notifier = new Notifier(config, store, metrics);

// ── REST API ──────────────────────────────────────────────────────────
const app = createApi(store);
const app = createApi(store, { metrics });
const httpServer = app.listen(config.api_port, () => {
console.log(`[api] Listening on port ${config.api_port}`);
});
Expand All @@ -68,6 +70,7 @@ async function main(): Promise<void> {
}

await notifier.notifyInvestors(event, investors);
metrics.recordEventProcessed();
};

// ── Start event polling ──────────────────────────────────────────────
Expand Down
21 changes: 8 additions & 13 deletions notification-service/src/notifier.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import nodemailer from "nodemailer";
import { ScoreChangedEvent, WebhookPayload, ServiceConfig } from "./types";
import { Store } from "./db";
import { Metrics } from "./metrics";

/** Upper bound on tracked dedup keys, so long-running processes don't grow unbounded. */
const MAX_TRACKED_NOTIFICATIONS = 5000;
Expand All @@ -12,6 +13,7 @@ const WEBHOOK_TIMEOUT_MS = 10_000;
export class Notifier {
private config: ServiceConfig;
private store: Store;
private metrics?: Metrics;
private transporter?: nodemailer.Transporter;
/**
* Keys of (event, investor) pairs already successfully notified, to guard
Expand All @@ -22,9 +24,10 @@ export class Notifier {
*/
private notifiedRecipients: Set<string> = new Set();

constructor(config: ServiceConfig, store: Store) {
constructor(config: ServiceConfig, store: Store, metrics?: Metrics) {
this.config = config;
this.store = store;
this.metrics = metrics;

if (config.email_transport) {
this.transporter = nodemailer.createTransport(config.email_transport);
Expand Down Expand Up @@ -82,21 +85,13 @@ export class Notifier {
try {
if (hasEmail && this.transporter && pref.email) {
await this.sendEmail(pref.email, subject, text);
this.store.recordNotification(
addr,
event.project_id,
"email",
event.ledger,
);
this.store.recordNotification(addr, event.project_id, "email", event.ledger);
this.metrics?.recordNotificationSent();
}
if (hasWebhook && pref.webhook_url) {
await this.sendWebhook(pref.webhook_url, event, addr);
this.store.recordNotification(
addr,
event.project_id,
"webhook",
event.ledger,
);
this.store.recordNotification(addr, event.project_id, "webhook", event.ledger);
this.metrics?.recordNotificationSent();
}
this.rememberRecipient(recipientKey);
} catch (err) {
Expand Down
Loading