refactor(core): Reduce memory usage in the Webhook node (#4640)

use file streaming to pass webhook binaries around
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2022-11-24 16:54:43 +01:00
committed by GitHub
parent 602b1e56d6
commit 07e4743a3e
16 changed files with 329 additions and 176 deletions

View File

@@ -1,8 +1,9 @@
import { promises as fs } from 'fs';
import fs from 'fs/promises';
import { jsonParse } from 'n8n-workflow';
import path from 'path';
import { v4 as uuid } from 'uuid';
import { IBinaryDataConfig, IBinaryDataManager } from '../Interfaces';
import { BinaryMetadata, IBinaryDataConfig, IBinaryDataManager } from '../Interfaces';
const PREFIX_METAFILE = 'binarymeta';
const PREFIX_PERSISTED_METAFILE = 'persistedmeta';
@@ -43,17 +44,47 @@ export class BinaryDataFileSystem implements IBinaryDataManager {
.then(() => {});
}
async getFileSize(identifier: string): Promise<number> {
const stats = await fs.stat(this.getBinaryPath(identifier));
return stats.size;
}
async copyBinaryFile(filePath: string, executionId: string): Promise<string> {
const binaryDataId = this.generateFileName(executionId);
await this.addBinaryIdToPersistMeta(executionId, binaryDataId);
await this.copyFileToLocalStorage(filePath, binaryDataId);
return binaryDataId;
}
async storeBinaryMetadata(identifier: string, metadata: BinaryMetadata) {
await fs.writeFile(this.getMetadataPath(identifier), JSON.stringify(metadata), {
encoding: 'utf-8',
});
}
async getBinaryMetadata(identifier: string): Promise<BinaryMetadata> {
return jsonParse(await fs.readFile(this.getMetadataPath(identifier), { encoding: 'utf-8' }));
}
async storeBinaryData(binaryBuffer: Buffer, executionId: string): Promise<string> {
const binaryDataId = this.generateFileName(executionId);
return this.addBinaryIdToPersistMeta(executionId, binaryDataId).then(async () =>
this.saveToLocalStorage(binaryBuffer, binaryDataId).then(() => binaryDataId),
);
await this.addBinaryIdToPersistMeta(executionId, binaryDataId);
await this.saveToLocalStorage(binaryBuffer, binaryDataId);
return binaryDataId;
}
async retrieveBinaryDataByIdentifier(identifier: string): Promise<Buffer> {
return this.retrieveFromLocalStorage(identifier);
}
getBinaryPath(identifier: string): string {
return path.join(this.storagePath, identifier);
}
getMetadataPath(identifier: string): string {
return path.join(this.storagePath, `${identifier}.metadata`);
}
async markDataForDeletionByExecutionId(executionId: string): Promise<void> {
const tt = new Date(new Date().getTime() + this.binaryDataTTL * 60000);
return fs.writeFile(
@@ -180,7 +211,7 @@ export class BinaryDataFileSystem implements IBinaryDataManager {
}
private generateFileName(prefix: string): string {
return `${prefix}_${uuid()}`;
return [prefix, uuid()].join('');
}
private getBinaryDataMetaPath() {
@@ -196,15 +227,19 @@ export class BinaryDataFileSystem implements IBinaryDataManager {
}
private async deleteFromLocalStorage(identifier: string) {
return fs.rm(path.join(this.storagePath, identifier));
return fs.rm(this.getBinaryPath(identifier));
}
private async copyFileToLocalStorage(source: string, identifier: string): Promise<void> {
await fs.cp(source, this.getBinaryPath(identifier));
}
private async saveToLocalStorage(data: Buffer, identifier: string) {
await fs.writeFile(path.join(this.storagePath, identifier), data);
await fs.writeFile(this.getBinaryPath(identifier), data);
}
private async retrieveFromLocalStorage(identifier: string): Promise<Buffer> {
const filePath = path.join(this.storagePath, identifier);
const filePath = this.getBinaryPath(identifier);
try {
return await fs.readFile(filePath);
} catch (e) {