feat: Implement Worker Service v2 with improved architecture
- Complete rewrite of the Worker Service following object-oriented principles. - Introduced a single long-lived database connection to reduce overhead. - Implemented event-driven queues to eliminate polling. - Added DRY utilities for pagination and settings management. - Reduced code size significantly from 1173 lines to approximately 600-700 lines. - Created various composed services including DatabaseManager, SessionManager, and SDKAgent. - Enhanced SSE broadcasting capabilities for real-time client updates. - Established a structured approach for session lifecycle management and event handling. - Introduced type safety with shared TypeScript interfaces for better maintainability.
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* DatabaseManager: Single long-lived database connection
|
||||
*
|
||||
* Responsibility:
|
||||
* - Manage single database connection for worker lifetime
|
||||
* - Provide centralized access to SessionStore and SessionSearch
|
||||
* - High-level database operations
|
||||
* - ChromaSync integration
|
||||
*/
|
||||
|
||||
import { SessionStore } from '../sqlite/SessionStore.js';
|
||||
import { SessionSearch } from '../sqlite/SessionSearch.js';
|
||||
import { ChromaSync } from '../sync/ChromaSync.js';
|
||||
import { logger } from '../../utils/logger.js';
|
||||
import type { DBSession } from '../worker-types.js';
|
||||
|
||||
export class DatabaseManager {
|
||||
private sessionStore: SessionStore | null = null;
|
||||
private sessionSearch: SessionSearch | null = null;
|
||||
private chromaSync: ChromaSync | null = null;
|
||||
|
||||
/**
|
||||
* Initialize database connection (once, stays open)
|
||||
*/
|
||||
async initialize(): Promise<void> {
|
||||
// Open database connection (ONCE)
|
||||
this.sessionStore = new SessionStore();
|
||||
this.sessionSearch = new SessionSearch();
|
||||
|
||||
// Initialize ChromaSync
|
||||
this.chromaSync = new ChromaSync('claude-mem');
|
||||
|
||||
// Start background backfill (fire-and-forget)
|
||||
this.chromaSync.ensureBackfilled().catch(() => {});
|
||||
|
||||
logger.info('DB', 'Database initialized');
|
||||
}
|
||||
|
||||
/**
|
||||
* Close database connection
|
||||
*/
|
||||
async close(): Promise<void> {
|
||||
if (this.sessionStore) {
|
||||
this.sessionStore.close();
|
||||
this.sessionStore = null;
|
||||
}
|
||||
if (this.sessionSearch) {
|
||||
this.sessionSearch.close();
|
||||
this.sessionSearch = null;
|
||||
}
|
||||
logger.info('DB', 'Database closed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SessionStore instance (throws if not initialized)
|
||||
*/
|
||||
getSessionStore(): SessionStore {
|
||||
if (!this.sessionStore) {
|
||||
throw new Error('Database not initialized');
|
||||
}
|
||||
return this.sessionStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SessionSearch instance (throws if not initialized)
|
||||
*/
|
||||
getSessionSearch(): SessionSearch {
|
||||
if (!this.sessionSearch) {
|
||||
throw new Error('Database not initialized');
|
||||
}
|
||||
return this.sessionSearch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ChromaSync instance (throws if not initialized)
|
||||
*/
|
||||
getChromaSync(): ChromaSync {
|
||||
if (!this.chromaSync) {
|
||||
throw new Error('ChromaSync not initialized');
|
||||
}
|
||||
return this.chromaSync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup orphaned sessions from previous runs
|
||||
* @returns Number of sessions cleaned
|
||||
*/
|
||||
cleanupOrphanedSessions(): number {
|
||||
return this.getSessionStore().cleanupOrphanedSessions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get session by ID (throws if not found)
|
||||
*/
|
||||
getSessionById(sessionDbId: number): {
|
||||
id: number;
|
||||
claude_session_id: string;
|
||||
sdk_session_id: string | null;
|
||||
project: string;
|
||||
user_prompt: string;
|
||||
} {
|
||||
const session = this.getSessionStore().getSessionById(sessionDbId);
|
||||
if (!session) {
|
||||
throw new Error(`Session ${sessionDbId} not found`);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark session as completed
|
||||
*/
|
||||
markSessionComplete(sessionDbId: number): void {
|
||||
this.getSessionStore().markSessionCompleted(sessionDbId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user