mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 12:44:07 -08:00
refactor(core): Log binary data file write errors (no-changelog) (#7237)
This PR adds logging for binary data file write errors, to capture why executions sometimes point to non-existing binary data files. See [Sentry error](https://n8nio.sentry.io/issues/4495134693/?alert_rule_id=14556563&alert_type=issue¬ification_uuid=4b50a5da-6ae9-472e-9658-984cca824762&project=4503924908883968&referrer=slack).
This commit is contained in:
parent
c0df5cdfd4
commit
e8e44f6b6e
|
@ -6,7 +6,8 @@ import type { Readable } from 'stream';
|
||||||
import type { BinaryMetadata } from 'n8n-workflow';
|
import type { BinaryMetadata } from 'n8n-workflow';
|
||||||
import { jsonParse } from 'n8n-workflow';
|
import { jsonParse } from 'n8n-workflow';
|
||||||
|
|
||||||
import type { IBinaryDataConfig, IBinaryDataManager } from '../Interfaces';
|
import { IBinaryDataConfig } from '../Interfaces';
|
||||||
|
import type { IBinaryDataManager } from '../Interfaces';
|
||||||
import { FileNotFoundError } from '../errors';
|
import { FileNotFoundError } from '../errors';
|
||||||
|
|
||||||
const executionExtractionRegexp =
|
const executionExtractionRegexp =
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import { readFile, stat } from 'fs/promises';
|
import { readFile, stat } from 'fs/promises';
|
||||||
import type { BinaryMetadata, IBinaryData, INodeExecutionData } from 'n8n-workflow';
|
import type { BinaryMetadata, INodeExecutionData } from 'n8n-workflow';
|
||||||
import prettyBytes from 'pretty-bytes';
|
import prettyBytes from 'pretty-bytes';
|
||||||
import type { Readable } from 'stream';
|
import type { Readable } from 'stream';
|
||||||
import { BINARY_ENCODING } from 'n8n-workflow';
|
import { BINARY_ENCODING, LoggerProxy as Logger, IBinaryData } from 'n8n-workflow';
|
||||||
import type { IBinaryDataConfig, IBinaryDataManager } from '../Interfaces';
|
import { IBinaryDataConfig } from '../Interfaces';
|
||||||
|
import type { IBinaryDataManager } from '../Interfaces';
|
||||||
import { BinaryDataFileSystem } from './FileSystem';
|
import { BinaryDataFileSystem } from './FileSystem';
|
||||||
import { binaryToBuffer } from './utils';
|
import { binaryToBuffer } from './utils';
|
||||||
|
import { LogCatch } from '../decorators/LogCatch.decorator';
|
||||||
|
|
||||||
export class BinaryDataManager {
|
export class BinaryDataManager {
|
||||||
static instance: BinaryDataManager | undefined;
|
static instance: BinaryDataManager | undefined;
|
||||||
|
@ -47,6 +49,7 @@ export class BinaryDataManager {
|
||||||
return BinaryDataManager.instance;
|
return BinaryDataManager.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@LogCatch((error) => Logger.error('Failed to copy binary data file', { error }))
|
||||||
async copyBinaryFile(
|
async copyBinaryFile(
|
||||||
binaryData: IBinaryData,
|
binaryData: IBinaryData,
|
||||||
filePath: string,
|
filePath: string,
|
||||||
|
@ -79,6 +82,7 @@ export class BinaryDataManager {
|
||||||
return binaryData;
|
return binaryData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@LogCatch((error) => Logger.error('Failed to write binary data file', { error }))
|
||||||
async storeBinaryData(
|
async storeBinaryData(
|
||||||
binaryData: IBinaryData,
|
binaryData: IBinaryData,
|
||||||
input: Buffer | Readable,
|
input: Buffer | Readable,
|
||||||
|
@ -162,6 +166,9 @@ export class BinaryDataManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@LogCatch((error) =>
|
||||||
|
Logger.error('Failed to copy all binary data files for execution', { error }),
|
||||||
|
)
|
||||||
async duplicateBinaryData(
|
async duplicateBinaryData(
|
||||||
inputData: Array<INodeExecutionData[] | null>,
|
inputData: Array<INodeExecutionData[] | null>,
|
||||||
executionId: string,
|
executionId: string,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import type {
|
import type { INode } from 'n8n-workflow';
|
||||||
INode,
|
import {
|
||||||
|
Workflow,
|
||||||
INodeCredentials,
|
INodeCredentials,
|
||||||
INodeParameters,
|
INodeParameters,
|
||||||
INodeTypeNameVersion,
|
INodeTypeNameVersion,
|
||||||
INodeTypes,
|
INodeTypes,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { Workflow } from 'n8n-workflow';
|
|
||||||
|
|
||||||
const TEMP_NODE_NAME = 'Temp-Node';
|
const TEMP_NODE_NAME = 'Temp-Node';
|
||||||
const TEMP_WORKFLOW_NAME = 'Temp-Workflow';
|
const TEMP_WORKFLOW_NAME = 'Temp-Workflow';
|
||||||
|
|
|
@ -19,20 +19,23 @@ import type {
|
||||||
IPinData,
|
IPinData,
|
||||||
IRun,
|
IRun,
|
||||||
IRunData,
|
IRunData,
|
||||||
IRunExecutionData,
|
|
||||||
ISourceData,
|
ISourceData,
|
||||||
ITaskData,
|
ITaskData,
|
||||||
ITaskDataConnections,
|
ITaskDataConnections,
|
||||||
ITaskDataConnectionsSource,
|
ITaskDataConnectionsSource,
|
||||||
IWaitingForExecution,
|
IWaitingForExecution,
|
||||||
IWaitingForExecutionSource,
|
IWaitingForExecutionSource,
|
||||||
IWorkflowExecuteAdditionalData,
|
|
||||||
NodeApiError,
|
NodeApiError,
|
||||||
NodeOperationError,
|
NodeOperationError,
|
||||||
Workflow,
|
Workflow,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
import {
|
||||||
|
LoggerProxy as Logger,
|
||||||
|
WorkflowOperationError,
|
||||||
|
IRunExecutionData,
|
||||||
|
IWorkflowExecuteAdditionalData,
|
||||||
WorkflowExecuteMode,
|
WorkflowExecuteMode,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { LoggerProxy as Logger, WorkflowOperationError } from 'n8n-workflow';
|
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import * as NodeExecuteFunctions from './NodeExecuteFunctions';
|
import * as NodeExecuteFunctions from './NodeExecuteFunctions';
|
||||||
|
|
||||||
|
|
30
packages/core/src/decorators/LogCatch.decorator.ts
Normal file
30
packages/core/src/decorators/LogCatch.decorator.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
|
|
||||||
|
export const LogCatch = (logFn: (error: unknown) => void) => {
|
||||||
|
return (target: unknown, propertyKey: string, descriptor: PropertyDescriptor) => {
|
||||||
|
const originalMethod = descriptor.value;
|
||||||
|
|
||||||
|
descriptor.value = function (...args: unknown[]) {
|
||||||
|
try {
|
||||||
|
const result: unknown = originalMethod.apply(this, args);
|
||||||
|
|
||||||
|
if (result && result instanceof Promise) {
|
||||||
|
return result.catch((error: unknown) => {
|
||||||
|
logFn(error);
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
logFn(error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return descriptor;
|
||||||
|
};
|
||||||
|
};
|
|
@ -13,7 +13,6 @@ import type {
|
||||||
INode,
|
INode,
|
||||||
INodeCredentialsDetails,
|
INodeCredentialsDetails,
|
||||||
INodeType,
|
INodeType,
|
||||||
INodeTypeData,
|
|
||||||
INodeTypes,
|
INodeTypes,
|
||||||
IRun,
|
IRun,
|
||||||
ITaskData,
|
ITaskData,
|
||||||
|
@ -24,7 +23,7 @@ import type {
|
||||||
WorkflowTestData,
|
WorkflowTestData,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import { ICredentialsHelper, NodeHelpers, WorkflowHooks } from 'n8n-workflow';
|
import { ICredentialsHelper, NodeHelpers, WorkflowHooks, INodeTypeData } from 'n8n-workflow';
|
||||||
import { Credentials } from '@/Credentials';
|
import { Credentials } from '@/Credentials';
|
||||||
|
|
||||||
import { predefinedNodesTypes } from './constants';
|
import { predefinedNodesTypes } from './constants';
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./*"]
|
"@/*": ["./*"]
|
||||||
},
|
},
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
// TODO: remove all options below this line
|
// TODO: remove all options below this line
|
||||||
"useUnknownInCatchVariables": false
|
"useUnknownInCatchVariables": false
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue