mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
Restore extractTarball
This commit is contained in:
parent
b2e0c9e4c9
commit
64606591c6
|
@ -3,9 +3,7 @@ import { ensureError, jsonParse } from 'n8n-workflow';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import readline from 'node:readline';
|
import readline from 'node:readline';
|
||||||
import { pipeline } from 'node:stream/promises';
|
|
||||||
import { Service } from 'typedi';
|
import { Service } from 'typedi';
|
||||||
import { Extract } from 'unzip-stream';
|
|
||||||
|
|
||||||
import { NotObjectLiteralError } from '@/errors/not-object-literal.error';
|
import { NotObjectLiteralError } from '@/errors/not-object-literal.error';
|
||||||
import { RowCountMismatchError } from '@/errors/row-count-mismatch.error';
|
import { RowCountMismatchError } from '@/errors/row-count-mismatch.error';
|
||||||
|
@ -28,7 +26,7 @@ import { DatabaseSchemaService } from '../database-schema.service';
|
||||||
@Service()
|
@Service()
|
||||||
export class DatabaseImportService {
|
export class DatabaseImportService {
|
||||||
private config: DatabaseImportConfig = {
|
private config: DatabaseImportConfig = {
|
||||||
importFilePath: '',
|
importFilePath: '/tmp/backup/n8n-db-export-2024-10-11.tar.gz',
|
||||||
extractDirPath: '/tmp/backup',
|
extractDirPath: '/tmp/backup',
|
||||||
truncateDestination: true, // @TODO: Only for dev, default it to `false` later
|
truncateDestination: true, // @TODO: Only for dev, default it to `false` later
|
||||||
};
|
};
|
||||||
|
@ -85,12 +83,7 @@ export class DatabaseImportService {
|
||||||
|
|
||||||
if (dbType !== 'postgresdb') throw new UnsupportedDestinationError(dbType);
|
if (dbType !== 'postgresdb') throw new UnsupportedDestinationError(dbType);
|
||||||
|
|
||||||
// @TODO: Stream instead of extracting to filesystem
|
await this.fsService.extractTarball(this.config.importFilePath, this.config.extractDirPath);
|
||||||
|
|
||||||
await pipeline(
|
|
||||||
fs.createReadStream(this.config.importFilePath),
|
|
||||||
Extract({ path: this.config.extractDirPath }),
|
|
||||||
);
|
|
||||||
|
|
||||||
this.manifest = await this.getManifest();
|
this.manifest = await this.getManifest();
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
import { FileNotFoundError } from 'n8n-core';
|
import { FileNotFoundError } from 'n8n-core';
|
||||||
import { ensureError } from 'n8n-workflow';
|
import { ensureError } from 'n8n-workflow';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { pipeline } from 'node:stream/promises';
|
||||||
|
import { createGunzip } from 'node:zlib';
|
||||||
|
import tar from 'tar-stream';
|
||||||
import { Service } from 'typedi';
|
import { Service } from 'typedi';
|
||||||
|
|
||||||
|
import { Logger } from '@/logging/logger.service';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class FilesystemService {
|
export class FilesystemService {
|
||||||
|
constructor(private readonly logger: Logger) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure a directory exists by checking or creating it.
|
* Ensure a directory exists by checking or creating it.
|
||||||
* @param dirPath Path to the directory to check or create.
|
* @param dirPath Path to the directory to check or create.
|
||||||
|
@ -46,4 +54,31 @@ export class FilesystemService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract a tarball to a given directory.
|
||||||
|
* @param tarballPath Path to the tarball file to extract.
|
||||||
|
* @param dstDir Path to the directory to extract the tarball into.
|
||||||
|
* @returns Paths to the extracted files.
|
||||||
|
*/
|
||||||
|
async extractTarball(tarballPath: string, dstDir: string) {
|
||||||
|
await this.checkAccessible(tarballPath); // @TODO: Clearer error if tarball missing
|
||||||
|
|
||||||
|
const extractedFilePaths: string[] = [];
|
||||||
|
|
||||||
|
const extract = tar.extract();
|
||||||
|
|
||||||
|
extract.on('entry', async (header, stream, next) => {
|
||||||
|
const filePath = path.join(dstDir, header.name);
|
||||||
|
await pipeline(stream, fs.createWriteStream(filePath));
|
||||||
|
extractedFilePaths.push(filePath);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
await pipeline(fs.createReadStream(tarballPath), createGunzip(), extract);
|
||||||
|
|
||||||
|
this.logger.info('[FilesystemService] Extracted tarball', { tarballPath });
|
||||||
|
|
||||||
|
return extractedFilePaths;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue