memory-engineering
Version:
Advanced Memory-Aware Code Context System with claude-flow-inspired architecture, showcasing MongoDB + Voyage AI strategic positioning
171 lines • 6.13 kB
JavaScript
/**
* MongoDB Backend Implementation
* Following claude-flow-main proven patterns for robust memory storage
*/
import { MongoClient } from 'mongodb';
import { MemoryBackendError } from './backend-interface.js';
export class MongoDBBackend {
config;
client;
db;
collection;
initialized = false;
constructor(config) {
this.config = config;
}
async initialize() {
if (this.initialized)
return;
try {
this.client = new MongoClient(this.config.connectionString);
await this.client.connect();
const dbName = this.config.databaseName || 'memory_engineering';
this.db = this.client.db(dbName);
this.collection = this.db.collection(this.config.collectionName || 'memories');
if (this.config.enableIndexes !== false) {
await this.createIndexes();
}
this.initialized = true;
}
catch (error) {
throw new MemoryBackendError('Failed to initialize MongoDB backend', { error });
}
}
async shutdown() {
if (this.client) {
await this.client.close();
delete this.client;
delete this.db;
delete this.collection;
}
this.initialized = false;
}
async store(entry) {
if (!this.collection) {
throw new MemoryBackendError('Backend not initialized');
}
try {
// Use replaceOne for clean upsert - following claude-flow pattern
const document = { ...entry, updatedAt: new Date() };
delete document._id;
await this.collection.replaceOne({ id: entry.id }, document, { upsert: true });
}
catch (error) {
throw new MemoryBackendError('Failed to store entry', { error, entryId: entry.id });
}
}
async retrieve(id) {
if (!this.collection) {
throw new MemoryBackendError('Backend not initialized');
}
try {
const entry = await this.collection.findOne({ id });
return entry || undefined;
}
catch (error) {
throw new MemoryBackendError('Failed to retrieve entry', { error, entryId: id });
}
}
async update(_id, entry) {
await this.store(entry);
}
async delete(id) {
if (!this.collection) {
throw new MemoryBackendError('Backend not initialized');
}
try {
await this.collection.deleteOne({ id });
}
catch (error) {
throw new MemoryBackendError('Failed to delete entry', { error, entryId: id });
}
}
async query(query) {
if (!this.collection) {
throw new MemoryBackendError('Backend not initialized');
}
try {
const filter = {};
if (query.projectPath)
filter.projectPath = query.projectPath;
if (query.memoryType)
filter.memoryType = query.memoryType;
if (query.tags && query.tags.length > 0)
filter.tags = { $in: query.tags };
if (query.startTime || query.endTime) {
filter.timestamp = {};
if (query.startTime)
filter.timestamp.$gte = query.startTime;
if (query.endTime)
filter.timestamp.$lte = query.endTime;
}
if (query.search) {
filter.$or = [
{ searchableText: { $regex: query.search, $options: 'i' } },
{ 'content.projectName': { $regex: query.search, $options: 'i' } },
{ 'content.corePurpose': { $regex: query.search, $options: 'i' } }
];
}
const cursor = this.collection.find(filter)
.sort({ timestamp: -1 })
.limit(query.limit || 50);
if (query.offset)
cursor.skip(query.offset);
return await cursor.toArray();
}
catch (error) {
throw new MemoryBackendError('Failed to query entries', { error, query });
}
}
async getAllEntries() {
if (!this.collection) {
throw new MemoryBackendError('Backend not initialized');
}
try {
return await this.collection.find({}).toArray();
}
catch (error) {
throw new MemoryBackendError('Failed to get all entries', { error });
}
}
async getHealthStatus() {
if (!this.db || !this.collection) {
return { healthy: false, error: 'Backend not initialized' };
}
try {
await this.db.admin().ping();
let metrics;
if (this.config.enableMetrics !== false) {
const count = await this.collection.countDocuments();
const stats = await this.db.stats();
metrics = {
entryCount: count,
dbSizeBytes: stats.dataSize || 0,
indexSizeBytes: stats.indexSize || 0
};
}
return { healthy: true, metrics };
}
catch (error) {
return {
healthy: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
async createIndexes() {
if (!this.collection)
return;
try {
await this.collection.createIndex({ id: 1 }, { unique: true, background: true });
await this.collection.createIndex({ projectPath: 1, memoryType: 1 }, { background: true });
await this.collection.createIndex({ timestamp: -1 }, { background: true });
await this.collection.createIndex({ tags: 1 }, { background: true });
await this.collection.createIndex({ 'metadata.version': 1 }, { background: true });
}
catch (error) {
// Index creation errors are non-fatal
}
}
}
//# sourceMappingURL=mongodb-backend.js.map