Skip to content

Commit 5077d59

Browse files
fix(ai): clean up conversation timers on module destroy
Prevent leaked TTL timers from keeping Jest alive and add test cleanup.
1 parent a7ea199 commit 5077d59

2 files changed

Lines changed: 15 additions & 1 deletion

File tree

apps/api/src/modules/ai/ai.service.spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ describe('AiService', () => {
8787
message: 'Tell me about the reentrancy finding',
8888
};
8989

90+
afterEach(() => {
91+
// Clear any lingering conversation timers so Jest can exit cleanly.
92+
service.clearConversation('user-1', 'audit-1');
93+
});
94+
9095
it('should be defined', () => {
9196
expect(service).toBeDefined();
9297
});

apps/api/src/modules/ai/ai.service.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
Injectable,
44
InternalServerErrorException,
55
NotFoundException,
6+
type OnModuleDestroy,
67
} from '@nestjs/common';
78
import { AiService as AiEngineService } from '@veridion/ai-engine';
89
import { logger } from '@veridion/logger';
@@ -46,7 +47,7 @@ const MAX_HISTORY_LENGTH = 50;
4647
const CONVERSATION_TTL_MS = 30 * 60 * 1000; // 30 minutes
4748

4849
@Injectable()
49-
export class AiService {
50+
export class AiService implements OnModuleDestroy {
5051
private readonly conversations = new Map<string, AiChatMessage[]>();
5152
private readonly conversationTimers = new Map<string, NodeJS.Timeout>();
5253

@@ -148,6 +149,14 @@ export class AiService {
148149
}
149150
}
150151

152+
onModuleDestroy(): void {
153+
for (const timer of this.conversationTimers.values()) {
154+
clearTimeout(timer);
155+
}
156+
this.conversations.clear();
157+
this.conversationTimers.clear();
158+
}
159+
151160
// ---- Private helpers ----
152161

153162
private getOrCreateHistory(key: string): AiChatMessage[] {

0 commit comments

Comments
 (0)