UNPKG

@spaik/mcp-server-roi

Version:

MCP server for AI ROI prediction and tracking with Monte Carlo simulations

162 lines 5.95 kB
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