refactor: Enhance GenerationJobManager and event transports for improved resource management

- Updated GenerationJobManager to prevent immediate cleanup of eventTransport upon job completion, allowing final events to transmit fully before cleanup.
- Added orphaned stream cleanup logic in GenerationJobManager to handle streams without corresponding jobs.
- Introduced getTrackedStreamIds method in both InMemoryEventTransport and RedisEventTransport for better management of orphaned streams.
- Improved comments for clarity on resource management and cleanup processes.
This commit is contained in:
Danny Avila 2025-12-15 09:44:27 -05:00
parent 10e9e2c008
commit c9ec1c31f0
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
4 changed files with 36 additions and 4 deletions

View file

@ -357,7 +357,10 @@ class GenerationJobManagerClass {
/**
* Mark job as complete.
* If cleanupOnComplete is true (default), immediately cleans up all job resources.
* If cleanupOnComplete is true (default), immediately cleans up job resources.
* Note: eventTransport is NOT cleaned up here to allow the final event to be
* fully transmitted. It will be cleaned up when subscribers disconnect or
* by the periodic cleanup job.
*/
async completeJob(streamId: string, error?: string): Promise<void> {
// Clear content state and run step buffer (Redis only)
@ -367,7 +370,8 @@ class GenerationJobManagerClass {
// Immediate cleanup if configured (default: true)
if (this._cleanupOnComplete) {
this.runtimeState.delete(streamId);
this.eventTransport.cleanup(streamId);
// Don't cleanup eventTransport here - let the done event fully transmit first.
// EventTransport will be cleaned up when subscribers disconnect or by periodic cleanup.
await this.jobStore.deleteJob(streamId);
} else {
// Only update status if keeping the job around
@ -443,7 +447,7 @@ class GenerationJobManagerClass {
// Immediate cleanup if configured (default: true)
if (this._cleanupOnComplete) {
this.runtimeState.delete(streamId);
this.eventTransport.cleanup(streamId);
// Don't cleanup eventTransport here - let the abort event fully transmit first.
await this.jobStore.deleteJob(streamId);
} else {
// Only update status if keeping the job around
@ -806,6 +810,14 @@ class GenerationJobManagerClass {
}
}
// Check eventTransport for orphaned streams (e.g., connections dropped without clean close)
// These are streams that exist in eventTransport but have no corresponding job
for (const streamId of this.eventTransport.getTrackedStreamIds()) {
if (!(await this.jobStore.hasJob(streamId)) && !this.runtimeState.has(streamId)) {
this.eventTransport.cleanup(streamId);
}
}
if (count > 0) {
logger.debug(`[GenerationJobManager] Cleaned up ${count} expired jobs`);
}