claude-flow-novice
Version:
Claude Flow Novice - Advanced orchestration platform for multi-agent AI workflows with CFN Loop architecture Includes Local RuVector Accelerator and all CFN skills for complete functionality.
168 lines (167 loc) • 6.43 kB
JavaScript
/**
* Database Service - Main Entry Point
*
* Unified database abstraction layer for Redis, SQLite, and PostgreSQL.
* Part of Task 0.4: Database Query Abstraction Layer (MVP)
*
* @example
* ```typescript
* const dbService = new DatabaseService({
* redis: { type: 'redis', host: 'localhost', port: 6379 },
* sqlite: { type: 'sqlite', database: './data.db' },
* postgres: { type: 'postgres', connectionString: 'postgresql://...' }
* });
*
* await dbService.connect();
*
* // Get data by correlation key across all databases
* const data = await dbService.getByCorrelationKey({
* type: 'task',
* id: 'abc123',
* entity: 'agent'
* });
* ```
*/ import { RedisAdapter } from './redis-adapter.js';
import { SQLiteAdapter } from './sqlite-adapter.js';
import { PostgresAdapter } from './postgres-adapter.js';
import { TransactionManager } from './transaction-manager.js';
import { buildCorrelationKey, parseCorrelationKey, buildTaskKey, buildAgentKey, buildSkillKey, buildExecutionKey } from './correlation.js';
import { DatabaseErrorCode, createDatabaseError } from './errors.js';
export class DatabaseService {
adapters = new Map();
transactionManager;
config;
constructor(config){
this.config = config;
this.transactionManager = new TransactionManager();
// Initialize adapters
if (config.redis) {
this.adapters.set('redis', new RedisAdapter(config.redis));
}
if (config.sqlite) {
this.adapters.set('sqlite', new SQLiteAdapter(config.sqlite));
}
if (config.postgres) {
this.adapters.set('postgres', new PostgresAdapter(config.postgres));
}
}
/**
* Connect to all configured databases
*/ async connect() {
const promises = Array.from(this.adapters.values()).map((adapter)=>adapter.connect());
await Promise.all(promises);
}
/**
* Disconnect from all databases
*/ async disconnect() {
const promises = Array.from(this.adapters.values()).map((adapter)=>adapter.disconnect());
await Promise.all(promises);
}
/**
* Get adapter for specific database
*/ getAdapter(type) {
const adapter = this.adapters.get(type);
if (!adapter) {
throw createDatabaseError(DatabaseErrorCode.CONNECTION_FAILED, `Database adapter not configured: ${type}`, undefined, {
type
});
}
return adapter;
}
/**
* Get record by correlation key across all databases
*/ async getByCorrelationKey(key) {
const correlationKeyString = buildCorrelationKey(key);
const result = {
correlationKey: correlationKeyString,
timestamp: new Date()
};
// Query each database in parallel
const promises = [];
if (this.adapters.has('redis')) {
promises.push(this.adapters.get('redis').get(correlationKeyString).then((data)=>{
if (data !== null && data !== undefined) result.redis = data;
}).catch((err)=>console.warn('Redis lookup failed:', err)));
}
if (this.adapters.has('sqlite')) {
promises.push(this.adapters.get('sqlite').get(correlationKeyString).then((data)=>{
if (data !== null && data !== undefined) result.sqlite = data;
}).catch((err)=>console.warn('SQLite lookup failed:', err)));
}
if (this.adapters.has('postgres')) {
promises.push(this.adapters.get('postgres').get(correlationKeyString).then((data)=>{
if (data !== null && data !== undefined) result.postgres = data;
}).catch((err)=>console.warn('PostgreSQL lookup failed:', err)));
}
await Promise.all(promises);
return result;
}
/**
* Execute cross-database transaction
*/ async executeTransaction(operations) {
const adapters = operations.map((op)=>this.getAdapter(op.database));
const ops = operations.map((op)=>op.operation);
return this.transactionManager.executeTransaction(adapters, ops);
}
/**
* Build correlation key
*/ buildCorrelationKey(key) {
return buildCorrelationKey(key);
}
/**
* Parse correlation key
*/ parseCorrelationKey(key) {
return parseCorrelationKey(key);
}
/**
* Get transaction manager
*/ getTransactionManager() {
return this.transactionManager;
}
/**
* Check if all configured databases are connected
*/ isConnected() {
return Array.from(this.adapters.values()).every((adapter)=>adapter.isConnected());
}
/**
* Get database statistics including connection pool metrics
*/ getStats() {
const poolStats = {};
// Get pool stats from each adapter
if (this.adapters.has('redis')) {
const adapter = this.adapters.get('redis');
poolStats.redis = adapter.getPoolStats?.();
}
if (this.adapters.has('sqlite')) {
const adapter = this.adapters.get('sqlite');
poolStats.sqlite = adapter.getPoolStats?.();
}
if (this.adapters.has('postgres')) {
const adapter = this.adapters.get('postgres');
poolStats.postgres = adapter.getPoolStats?.();
}
return {
adapters: {
redis: this.adapters.has('redis') && this.adapters.get('redis').isConnected(),
sqlite: this.adapters.has('sqlite') && this.adapters.get('sqlite').isConnected(),
postgres: this.adapters.has('postgres') && this.adapters.get('postgres').isConnected()
},
transactions: {
active: this.transactionManager.getActiveCount()
},
connectionPools: poolStats
};
}
}
// Re-export types and utilities
export * from './types.js';
export * from './errors.js';
export * from './correlation.js';
export { RedisAdapter } from './redis-adapter.js';
export { SQLiteAdapter } from './sqlite-adapter.js';
export { PostgresAdapter } from './postgres-adapter.js';
export { TransactionManager } from './transaction-manager.js';
export { ConnectionPoolManager } from './connection-pool-manager.js';
// Re-export correlation utilities
export { buildTaskKey, buildAgentKey, buildSkillKey, buildExecutionKey };
//# sourceMappingURL=index.js.map