Skip to content

Commit 9dd4eac

Browse files
author
Sorra
committed
SB-0MN77JYZ513EIHHI: Extract LifecycleManager module from src/index.ts
- Create LifecycleManager class with comprehensive startup/shutdown lifecycle management - Move startup notifications, recovery, and status restoration into dedicated module - Implement graceful shutdown handling with SIGTERM/SIGINT signal handlers - Add status message cleanup and lost item recovery on shutdown - Add STARTUP_NOTIFICATION_CHANNEL_ID config option to bot.ts - Replace inline startup/shutdown logic in index.ts with LifecycleManager integration - Create comprehensive unit tests (30 test cases) for LifecycleManager - Maintain backward compatibility through legacy exports All 162 tests passing.
1 parent b690803 commit 9dd4eac

5 files changed

Lines changed: 1054 additions & 4 deletions

File tree

src/config/bot.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ export const botConfigSchema = z.object({
4242

4343
// File URL configuration
4444
ALLOWED_FILE_URL_USERS: z.string().optional().transform(v => v ? v.split(',').map(id => id.trim()) : []),
45+
46+
// Lifecycle configuration
47+
STARTUP_NOTIFICATION_CHANNEL_ID: z.string().optional(),
4548
});
4649

4750
const parsed = botConfigSchema.safeParse(process.env);

src/index.ts

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ import { postCliErrorReport } from "./discord/cli-error-report.js";
99
import { CrawlCommandHandler } from "./handlers/CrawlCommandHandler.js";
1010
import { StatsCommandHandler } from "./handlers/StatsCommandHandler.js";
1111
import { RecentCommandHandler } from "./handlers/RecentCommandHandler.js";
12-
import { startBot } from "./lifecycle/startup.js";
13-
import { createShutdownController } from "./lifecycle/shutdown.js";
12+
import { LifecycleManager } from "./lifecycle/LifecycleManager.js";
1413
import {
1514
formatMissingCrawlSeedMessage,
1615
formatQueueFailureMessage,
@@ -2139,8 +2138,50 @@ const bot = new DiscordBot({
21392138
// Startup and Shutdown
21402139
// ============================================================================
21412140

2142-
createShutdownController(logger);
2143-
void startBot(() => bot.start(), logger);
2141+
// Create lifecycle manager for comprehensive startup/shutdown management
2142+
const lifecycleManager = new LifecycleManager({
2143+
logger,
2144+
client: bot.client,
2145+
startupNotification: config.STARTUP_NOTIFICATION_CHANNEL_ID
2146+
? {
2147+
channelId: config.STARTUP_NOTIFICATION_CHANNEL_ID,
2148+
includeTimestamp: true,
2149+
}
2150+
: undefined,
2151+
shutdownConfig: {
2152+
timeoutMs: 30000,
2153+
cleanupStatusMessages: true,
2154+
performLostItemRecovery: true,
2155+
},
2156+
eventListeners: {
2157+
onStartupBegin: () => {
2158+
logger.info("Bot startup sequence beginning");
2159+
},
2160+
onStartupComplete: () => {
2161+
logger.info("Bot startup sequence completed");
2162+
},
2163+
onShutdownBegin: (signal: string) => {
2164+
logger.info(`Bot shutdown initiated by ${signal}`);
2165+
},
2166+
onShutdownComplete: () => {
2167+
logger.info("Bot shutdown sequence completed");
2168+
},
2169+
},
2170+
});
2171+
2172+
// Start the bot with lifecycle management
2173+
void (async () => {
2174+
try {
2175+
await bot.start();
2176+
await lifecycleManager.performStartup();
2177+
} catch (error) {
2178+
logger.error("Failed to start bot", {
2179+
error: error instanceof Error ? error.message : String(error),
2180+
});
2181+
process.exit(1);
2182+
}
2183+
})();
21442184

21452185
// Export internals for testing
21462186
export { processUrlWithProgress };
2187+
export { lifecycleManager };

0 commit comments

Comments
 (0)