fix(lifecycle): clean up service subscriptions, proxy retries, and stale runtime state on shutdown

This commit is contained in:
2026-03-21 22:30:30 +00:00
parent c7fe7aeb50
commit 39ff159bf7
10 changed files with 115 additions and 27 deletions

View File

@@ -254,6 +254,7 @@ export class DcRouter {
// Service lifecycle management
public serviceManager: plugins.taskbuffer.ServiceManager;
private serviceSubjectSubscription?: plugins.smartrx.rxjs.Subscription;
public smartAcmeReady = false;
// TypedRouter for API endpoints
@@ -516,7 +517,7 @@ export class DcRouter {
}
// Wire up aggregated events for logging
this.serviceManager.serviceSubject.subscribe((event) => {
this.serviceSubjectSubscription = this.serviceManager.serviceSubject.subscribe((event) => {
const level = event.type === 'failed' ? 'error' : event.type === 'retrying' ? 'warn' : 'info';
logger.log(level as any, `Service '${event.serviceName}': ${event.type}`, {
state: event.state,
@@ -639,6 +640,13 @@ export class DcRouter {
*/
private async setupSmartProxy(): Promise<void> {
logger.log('info', 'Setting up SmartProxy...');
// Clean up any existing SmartProxy instance (e.g. from a retry)
if (this.smartProxy) {
this.smartProxy.removeAllListeners();
this.smartProxy = undefined;
}
let routes: plugins.smartproxy.IRouteConfig[] = [];
let acmeConfig: plugins.smartproxy.IAcmeOptions | undefined;
@@ -1126,6 +1134,12 @@ export class DcRouter {
public async stop() {
logger.log('info', 'Stopping DcRouter services...');
// Unsubscribe from service events before stopping services
if (this.serviceSubjectSubscription) {
this.serviceSubjectSubscription.unsubscribe();
this.serviceSubjectSubscription = undefined;
}
// ServiceManager handles reverse-dependency-ordered shutdown
await this.serviceManager.stop();