@spaik/mcp-server-roi
Version:
MCP server for AI ROI prediction and tracking with Monte Carlo simulations
162 lines • 5.95 kB
JavaScript
import { rateLimitedMcpDb } from './rate-limited-client.js';
import { batchProcessors } from '../utils/batch-processor.js';
import { createLogger } from '../utils/logger.js';
const logger = createLogger({ module: 'batch-operations' });
/**
* Batch operations for use cases
*/
export const useCaseBatch = {
// Batch insert processor
insert: batchProcessors.createInsertProcessor('use_cases', async (items) => {
const { data, error } = await rateLimitedMcpDb
.from('use_cases')
.insert(items)
.select();
if (error) {
logger.error('Batch insert failed for use_cases', error);
throw error;
}
return data || [];
}),
// Batch update processor
update: batchProcessors.createUpdateProcessor('use_cases', async (items) => {
// Group updates by common fields for efficiency
const updates = await Promise.all(items.map(item => {
const { id, ...updates } = item;
return rateLimitedMcpDb
.from('use_cases')
.update(updates)
.eq('id', id)
.select()
.single();
}));
return updates
.filter(result => !result.error)
.map(result => result.data);
})
};
/**
* Batch operations for projections
*/
export const projectionBatch = {
// Batch insert processor
insert: batchProcessors.createInsertProcessor('projections', async (items) => {
const { data, error } = await rateLimitedMcpDb
.from('projections')
.insert(items)
.select();
if (error) {
logger.error('Batch insert failed for projections', error);
throw error;
}
return data || [];
})
};
/**
* Batch fetch operations with optimal chunking
*/
export class BatchFetcher {
/**
* Fetch multiple records by IDs with optimal batching
*/
static async fetchByIds(table, ids, options) {
const batchSize = options?.batchSize || 100;
const select = options?.select || '*';
logger.debug(`Batch fetching ${ids.length} records from ${table}`);
// Create ID chunks
const chunks = [];
for (let i = 0; i < ids.length; i += batchSize) {
chunks.push(ids.slice(i, i + batchSize));
}
// Fetch all chunks in parallel (with rate limiting)
const results = await Promise.all(chunks.map(async (chunk) => {
const { data, error } = await rateLimitedMcpDb
.from(table)
.select(select)
.in('id', chunk);
if (error) {
logger.error(`Batch fetch failed for ${table}`, error);
throw error;
}
return (data || []);
}));
// Flatten results
return results.flat();
}
/**
* Fetch related records with optimal query strategy
*/
static async fetchRelated(table, parentField, parentIds, options) {
const batchSize = options?.batchSize || 50;
const select = options?.select || '*';
logger.debug(`Batch fetching related records from ${table} for ${parentIds.length} parents`);
// Create parent ID chunks
const chunks = [];
for (let i = 0; i < parentIds.length; i += batchSize) {
chunks.push(parentIds.slice(i, i + batchSize));
}
// Fetch all chunks
const results = await Promise.all(chunks.map(async (chunk) => {
let query = rateLimitedMcpDb
.from(table)
.select(select)
.in(parentField, chunk);
if (options?.orderBy) {
query = query.order(options.orderBy);
}
const { data, error } = await query;
if (error) {
logger.error(`Batch fetch related failed for ${table}`, error);
throw error;
}
return (data || []);
}));
// Group by parent ID
const grouped = new Map();
for (const records of results) {
for (const record of records) {
const parentId = record[parentField];
if (!grouped.has(parentId)) {
grouped.set(parentId, []);
}
grouped.get(parentId).push(record);
}
}
return grouped;
}
}
/**
* Example usage of batch operations
*/
export async function exampleBatchOperations() {
// Example 1: Batch insert use cases
const useCases = [
{
project_id: 'uuid-1',
name: 'Use Case 1',
category: 'automation',
current_state: { volume_per_month: 1000, cost_per_transaction: 10 },
future_state: { automation_percentage: 0.8, error_reduction: 0.9 },
implementation: { complexity_score: 5, integration_points: 3 }
},
// ... more use cases
];
// Add to batch - these will be automatically batched and processed
const insertPromises = useCases.map(uc => useCaseBatch.insert.add(uc));
const insertedUseCases = await Promise.all(insertPromises);
logger.info('Batch inserted use cases', { count: insertedUseCases.length });
// Example 2: Batch fetch by IDs
const projectIds = ['uuid-1', 'uuid-2', 'uuid-3'];
const projects = await BatchFetcher.fetchByIds('projects', projectIds, {
select: 'id, project_name, client_name, industry'
});
logger.info('Batch fetched projects', { count: projects.length });
// Example 3: Batch fetch related records
const useCasesByProject = await BatchFetcher.fetchRelated('use_cases', 'project_id', projectIds, {
orderBy: 'created_at'
});
logger.info('Batch fetched related use cases', {
projectCount: useCasesByProject.size
});
}
//# sourceMappingURL=batch-operations.js.map