import { LogicManager } from './logicManager.js';
import { LogicalSystem, Operation, LogicResult } from './types.js';
import { Loggers } from './utils/logger.js';
const logger = Loggers.server;
export interface BatchRequest {
id?: string;
system: LogicalSystem;
operation: Operation;
input: string;
format?: 'natural' | 'symbolic' | 'mixed';
additionalContext?: string;
}
export interface BatchResult {
id?: string;
success: boolean;
result?: LogicResult;
error?: string;
processingTime: number;
}
export interface BatchSummary {
total: number;
successful: number;
failed: number;
totalTime: number;
averageTime: number;
results: BatchResult[];
}
export class BatchProcessor {
private logicManager: LogicManager;
private static readonly MAX_BATCH_SIZE = 50;
private static readonly MAX_CONCURRENT = 10;
constructor(logicManager: LogicManager) {
this.logicManager = logicManager;
}
/**
* Process multiple logic requests in batch
* @param requests Array of batch requests
* @param options Processing options
* @returns Batch summary with all results
*/
async processBatch(
requests: BatchRequest[],
options: {
failFast?: boolean;
concurrent?: boolean;
maxConcurrent?: number;
} = {}
): Promise<BatchSummary> {
// Safety check on batch size
if (requests.length > BatchProcessor.MAX_BATCH_SIZE) {
throw new Error(
`Batch size ${requests.length} exceeds maximum ${BatchProcessor.MAX_BATCH_SIZE}. ` +
`Split into smaller batches for better performance and memory management.`
);
}
const startTime = Date.now();
const results: BatchResult[] = [];
let successCount = 0;
let failureCount = 0;
logger.info(`Processing batch of ${requests.length} requests`, {
concurrent: options.concurrent || false,
failFast: options.failFast || false
});
if (options.concurrent) {
// Process requests concurrently with limit
const maxConcurrent = Math.min(
options.maxConcurrent || BatchProcessor.MAX_CONCURRENT,
BatchProcessor.MAX_CONCURRENT
);
for (let i = 0; i < requests.length; i += maxConcurrent) {
const batch = requests.slice(i, i + maxConcurrent);
const batchPromises = batch.map(req => this.processRequest(req));
const batchResults = await Promise.allSettled(batchPromises);
for (const settled of batchResults) {
if (settled.status === 'fulfilled') {
results.push(settled.value);
if (settled.value.success) {
successCount++;
} else {
failureCount++;
if (options.failFast) break;
}
} else {
// Promise rejected
failureCount++;
results.push({
success: false,
error: settled.reason,
processingTime: 0
});
if (options.failFast) break;
}
}
if (options.failFast && failureCount > 0) break;
}
} else {
// Process requests sequentially
for (const request of requests) {
const result = await this.processRequest(request);
results.push(result);
if (result.success) {
successCount++;
} else {
failureCount++;
if (options.failFast) break;
}
}
}
const totalTime = Date.now() - startTime;
const summary: BatchSummary = {
total: requests.length,
successful: successCount,
failed: failureCount,
totalTime,
averageTime: totalTime / results.length,
results
};
logger.info(`Batch processing complete`, {
total: summary.total,
successful: summary.successful,
failed: summary.failed,
totalTime: summary.totalTime
});
return summary;
}
/**
* Process a single request with timing
*/
private async processRequest(request: BatchRequest): Promise<BatchResult> {
const startTime = Date.now();
try {
// Reset modal system if needed
if (request.system === 'modal') {
this.logicManager.setModalSystem('K');
}
// Handle modal system from additionalContext
if (request.system === 'modal' && request.additionalContext) {
const modalSystemMatch = request.additionalContext.match(/system[:\s]+([A-Z0-9]+)/i);
if (modalSystemMatch) {
const requestedSystem = modalSystemMatch[1].toUpperCase();
const validSystems = ['K', 'T', 'D', 'B', 'K4', 'KB', 'S4', 'S5', 'KD45'];
if (validSystems.includes(requestedSystem)) {
this.logicManager.setModalSystem(requestedSystem as any);
}
}
}
const result = await this.logicManager.process(
request.system,
request.operation,
request.input,
request.format || 'natural',
request.additionalContext
);
const processingTime = Date.now() - startTime;
return {
id: request.id,
success: result.status === 'success',
result,
processingTime
};
} catch (error) {
const processingTime = Date.now() - startTime;
return {
id: request.id,
success: false,
error: error instanceof Error ? error.message : String(error),
processingTime
};
}
}
/**
* Validate multiple arguments at once
* Convenience method for validation-only batches
*/
async validateBatch(
arguments_list: Array<{
id?: string;
system: LogicalSystem;
argument: string;
format?: 'natural' | 'symbolic' | 'mixed';
}>
): Promise<Array<{ id?: string; valid: boolean; explanation?: string }>> {
const requests: BatchRequest[] = arguments_list.map(arg => ({
id: arg.id,
system: arg.system,
operation: 'validate',
input: arg.argument,
format: arg.format || 'natural'
}));
const summary = await this.processBatch(requests);
return summary.results.map(result => ({
id: result.id,
valid: result.success && result.result?.status === 'success',
explanation: result.result?.message || result.error
}));
}
}