From 4a449d8c676cb788ade46d32c71a26e47f9cd7e1 Mon Sep 17 00:00:00 2001 From: Nikhil-Doye Date: Mon, 27 Oct 2025 20:23:23 -0400 Subject: [PATCH] Refactor NodeConfiguration and enhance concurrency handling - Moved the retrieval of the latest node data to a more appropriate location in NodeConfiguration, ensuring the most up-to-date configuration is used. - Updated the ConcurrencyLimiter to correctly handle the queue resolution by passing `undefined` to the next function, improving clarity and functionality. - Enhanced the DatabaseConnectionManager to securely merge connection updates while excluding sensitive fields, ensuring better security practices. - Made executionId optional in ExecutionEngine methods, providing more flexibility in execution handling. - Improved JSON parsing validation to allow extra fields, enhancing the robustness of the parsing process. - Updated circular dependency detection in WorkflowValidationEngine to utilize a Set for improved performance and clarity. --- src/components/NodeConfiguration.tsx | 9 +++++---- src/services/concurrencyLimiter.ts | 4 ++-- src/services/databaseConnectionManager.ts | 16 ++++++++++++++-- src/services/executionEngine.ts | 14 +++++++------- src/services/robustJsonParser.ts | 9 ++++----- src/services/workflowValidationEngine.ts | 6 ++++-- 6 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/components/NodeConfiguration.tsx b/src/components/NodeConfiguration.tsx index 715e234..802661b 100644 --- a/src/components/NodeConfiguration.tsx +++ b/src/components/NodeConfiguration.tsx @@ -405,6 +405,11 @@ export const NodeConfiguration: React.FC = ({ const [optimizationResult, setOptimizationResult] = useState(""); const [isPreviewingOptimization, setIsPreviewingOptimization] = useState(false); + + // Get the latest node data from the store to ensure we have the most up-to-date config + const currentNode = currentWorkflow?.nodes.find((node) => node.id === nodeId); + const currentData = currentNode?.data || data; + const [originalPrompt, setOriginalPrompt] = useState( (currentData.config && currentData.config.prompt) || "" ); @@ -414,10 +419,6 @@ export const NodeConfiguration: React.FC = ({ const [showLabelDialog, setShowLabelDialog] = useState(false); const [pendingLabel, setPendingLabel] = useState(""); - // Get the latest node data from the store to ensure we have the most up-to-date config - const currentNode = currentWorkflow?.nodes.find((node) => node.id === nodeId); - const currentData = currentNode?.data || data; - const handleConfigChange = (key: string, value: any) => { updateNode(nodeId, { config: { diff --git a/src/services/concurrencyLimiter.ts b/src/services/concurrencyLimiter.ts index a1f4cce..abb85ce 100644 --- a/src/services/concurrencyLimiter.ts +++ b/src/services/concurrencyLimiter.ts @@ -6,7 +6,7 @@ export class ConcurrencyLimiter { private maxConcurrency: number; private running: number = 0; - private queue: Array<() => void> = []; + private queue: Array<(value: unknown) => void> = []; constructor(maxConcurrency: number = 5) { this.maxConcurrency = Math.max(1, maxConcurrency); @@ -31,7 +31,7 @@ export class ConcurrencyLimiter { // Process next item in queue if any const nextResolve = this.queue.shift(); if (nextResolve) { - nextResolve(); + nextResolve(undefined); } } } diff --git a/src/services/databaseConnectionManager.ts b/src/services/databaseConnectionManager.ts index 61193e5..d986d0d 100644 --- a/src/services/databaseConnectionManager.ts +++ b/src/services/databaseConnectionManager.ts @@ -186,9 +186,21 @@ class DatabaseConnectionManager { const connection = this.connections.get(id); if (!connection) return false; + // Merge connection with updates first + const mergedConnection = { ...connection, ...updates }; + // Remove id and status as required by secureCredentials + const { + id: _, + status: __, + ...connectionWithoutIdStatus + } = mergedConnection; + // SECURITY: Handle credential updates securely - const secureUpdates = await this.secureCredentials(updates, id); - const updatedConnection = { ...connection, ...secureUpdates }; + const secureUpdates = await this.secureCredentials( + connectionWithoutIdStatus, + id + ); + const updatedConnection = { ...connection, ...updates, ...secureUpdates }; // Validate credentials if connection details are being updated if (this.hasConnectionDetailsChanged(updates)) { diff --git a/src/services/executionEngine.ts b/src/services/executionEngine.ts index a61e167..7d876f2 100644 --- a/src/services/executionEngine.ts +++ b/src/services/executionEngine.ts @@ -521,7 +521,7 @@ export class ExecutionEngine { data?: any, error?: string ) => void, - executionId: string + executionId: string = "" ): Promise { plan.status = "running"; plan.startTime = new Date(); @@ -550,7 +550,7 @@ export class ExecutionEngine { data?: any, error?: string ) => void, - executionId: string + executionId: string = "" ): Promise { const executionOrder = this.getExecutionOrder(plan.nodes, plan.edges); @@ -602,7 +602,7 @@ export class ExecutionEngine { data?: any, error?: string ) => void, - executionId: string + executionId: string = "" ): Promise { const parallelGroups = this.createParallelGroups( plan.nodes, @@ -637,7 +637,7 @@ export class ExecutionEngine { data?: any, error?: string ) => void, - executionId: string + executionId: string = "" ): Promise { const maxConcurrency = group.maxConcurrency || @@ -687,7 +687,7 @@ export class ExecutionEngine { data?: any, error?: string ) => void, - executionId: string + executionId: string = "" ): Promise { const executionOrder = this.getExecutionOrder(plan.nodes, plan.edges); const visited = new Set(); @@ -762,7 +762,7 @@ export class ExecutionEngine { data?: any, error?: string ) => void, - executionId: string + executionId: string = "" ): Promise { for (const branch of branches) { const shouldExecuteTrue = await this.evaluateCondition( @@ -924,7 +924,7 @@ export class ExecutionEngine { data?: any, error?: string ) => void, - executionId: string + executionId: string = "" ): Promise { context.status = "running"; context.startTime = new Date(); diff --git a/src/services/robustJsonParser.ts b/src/services/robustJsonParser.ts index dc8d4e1..26fd5ee 100644 --- a/src/services/robustJsonParser.ts +++ b/src/services/robustJsonParser.ts @@ -277,6 +277,7 @@ export function parseAndValidate( strictMode?: boolean; fallbackValue?: T; logAttempts?: boolean; + allowExtra?: boolean; } = {} ): ParseResult & { validationErrors?: string[] } { const parseResult = parseRobustJson(input, options); @@ -285,11 +286,9 @@ export function parseAndValidate( return parseResult; } - const validation = validateJsonStructure( - parseResult.data, - requiredFields, - options - ); + const validation = validateJsonStructure(parseResult.data, requiredFields, { + allowExtra: options.allowExtra, + }); if (!validation.isValid) { return { diff --git a/src/services/workflowValidationEngine.ts b/src/services/workflowValidationEngine.ts index 1149068..286ad8c 100644 --- a/src/services/workflowValidationEngine.ts +++ b/src/services/workflowValidationEngine.ts @@ -199,14 +199,16 @@ export class WorkflowValidationEngine { // Check for circular dependencies const circularDeps = this.detectCircularDependencies(nodeIds, edges); - if (circularDeps.length > 0) { + if (circularDeps.size > 0) { result.isValid = false; result.errors.push({ id: "circular_dependency", severity: "error", type: "circular_dependency", nodeIds: Array.from(circularDeps), - message: `Circular dependencies detected: ${circularDeps.join(", ")}`, + message: `Circular dependencies detected: ${Array.from( + circularDeps + ).join(", ")}`, suggestion: "Remove the circular connections between nodes to create a valid execution path", });