PYAE1994's picture
Upload folder using huggingface_hub
dd480ef verified
/**
* Reliability Validation Utilities
* Checks for retry policies, fallbacks, monitoring presence
*/
import type { WorkflowGraph, N8nWorkflow } from '../../apps/worker/src/types/workflow';
export interface ReliabilityCheckResult {
passed: boolean;
score: number;
findings: string[];
recommendations: string[];
}
export function checkReliability(workflow: N8nWorkflow, graph: WorkflowGraph): ReliabilityCheckResult {
const findings: string[] = [];
const recommendations: string[] = [];
let deductions = 0;
// Check retry on external API nodes
const externalNodes = workflow.nodes.filter((n) =>
n.type.includes('httpRequest') ||
n.type.includes('openAi') ||
n.type.includes('telegram') ||
n.type.includes('slack') ||
n.type.includes('gmail'),
);
externalNodes.forEach((node) => {
if (!node.retryOnFail) {
findings.push(`Node "${node.name}" calls external service without retry policy`);
recommendations.push(`Add retryOnFail: true, maxTries: 3, waitBetweenTries: 1000 to "${node.name}"`);
deductions += 10;
}
});
// Check for error workflow
if (!workflow.settings?.errorWorkflow) {
findings.push('No error workflow configured for global error handling');
recommendations.push('Set settings.errorWorkflow to an alert/notification workflow ID');
deductions += 8;
}
// Check for monitoring nodes
const monitoringNodes = graph.nodes.filter((n) => n.layer === 'monitoring');
if (monitoringNodes.length === 0) {
findings.push('No monitoring layer nodes detected in workflow');
recommendations.push('Add at least one structured logging or notification node');
deductions += 10;
}
// Check for fallback nodes on critical nodes
const criticalWithoutFallback = graph.nodes.filter(
(n) => n.isCritical && !n.fallbackNodeId,
);
if (criticalWithoutFallback.length > 0) {
criticalWithoutFallback.forEach((n) => {
findings.push(`Critical node "${n.label}" has no fallback path`);
recommendations.push(`Add fallbackNodeId to "${n.label}" pointing to an error handler`);
deductions += 8;
});
}
const score = Math.max(0, 100 - deductions);
return {
passed: deductions < 30,
score,
findings,
recommendations,
};
}