feat(web): wire domain events into realtime stream

This commit is contained in:
jjbrunton committed 2026-08-08 16:00:17 +01:00
1 parent 8c8ff11fd7
commit d5f0175dc2
6 files changed
+155 -1

No files matched your search

+26
View File
@@ -1,6 +1,7 @@
import type { AppContainer } from './bootstrap.js';
import { withRetry } from './utils/retry.js';
import { isSkip } from './services/processor.js';
import { reportDeliveryResult, reportInvitationCooldown } from './web/event-reporting.js';
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
@@ -93,6 +94,7 @@ export async function runMainLoop(app: AppContainer): Promise<void> {
let lastPausedLog = 0;
let lastCooldownLog = 0;
let reportedCooldownUntil: number | null = null;
const COOLDOWN_LOG_INTERVAL_MS = 5 * 60_000;
while (!isShuttingDown) {
@@ -110,6 +112,10 @@ export async function runMainLoop(app: AppContainer): Promise<void> {
// pull new posts — they'd just queue up and skip. Wait the cooldown out.
const cooldown = chatService.getInvitationCooldown();
if (cooldown) {
if (webServer && reportedCooldownUntil !== cooldown.until) {
reportInvitationCooldown(webServer.dashboardEvents, cooldown);
reportedCooldownUntil = cooldown.until;
}
const minutesLeft = Math.ceil((cooldown.until - Date.now()) / 60_000);
if (Date.now() - lastCooldownLog > COOLDOWN_LOG_INTERVAL_MS) {
logger.warn(`Chat invitation cooldown active — ~${minutesLeft}m left. ${cooldown.reason}`);
@@ -122,6 +128,10 @@ export async function runMainLoop(app: AppContainer): Promise<void> {
await sleep(config.reddit.pollIntervalMs);
continue;
}
if (webServer && reportedCooldownUntil !== null) {
reportInvitationCooldown(webServer.dashboardEvents, null);
reportedCooldownUntil = null;
}
lastCooldownLog = 0;
const posts = await monitorService.getUnprocessedPosts();
@@ -242,6 +252,14 @@ export async function runMainLoop(app: AppContainer): Promise<void> {
);
webServer?.pushLog('info', `✅ Message sent to u/${post.author} (${currentCount}/${config.rateLimit.maxMessagesPerHour} this hour)`);
webServer?.updateStats(currentCount);
if (webServer) {
reportDeliveryResult(webServer.dashboardEvents, {
success: true,
messageId: post.id,
username: post.author,
conversationId: chat.roomId,
});
}
} else {
postsRepo.setError(post.id, 'Failed to send message');
webServer?.logActivity(
@@ -251,6 +269,14 @@ export async function runMainLoop(app: AppContainer): Promise<void> {
postImageUrl ?? undefined,
);
webServer?.pushLog('error', `❌ Failed to send message to u/${post.author}`);
if (webServer) {
reportDeliveryResult(webServer.dashboardEvents, {
success: false,
messageId: post.id,
username: post.author,
error: 'Chat service did not create a conversation',
});
}
}
return success;