fix(fs): Improve waitForFileToBeReady function for file stability detection
This commit is contained in:
parent
d557e4b4fe
commit
4c4e41b158
@ -1,5 +1,12 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-01-07 - 11.1.1 - fix(fs)
|
||||
Improve waitForFileToBeReady function for file stability detection
|
||||
|
||||
- Enhanced error handling and file stability checks in waitForFileToBeReady function
|
||||
- Added timeout feature for file readiness check
|
||||
- Improved directory access check before file availability check
|
||||
|
||||
## 2025-01-07 - 11.1.0 - feat(SmartFile)
|
||||
Add rename functionality to SmartFile class
|
||||
|
||||
|
@ -49,7 +49,7 @@
|
||||
"@push.rocks/smartjson": "^5.0.20",
|
||||
"@push.rocks/smartmime": "^2.0.4",
|
||||
"@push.rocks/smartpath": "^5.0.18",
|
||||
"@push.rocks/smartpromise": "^4.0.4",
|
||||
"@push.rocks/smartpromise": "^4.1.0",
|
||||
"@push.rocks/smartrequest": "^2.0.23",
|
||||
"@push.rocks/smartstream": "^3.2.5",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
@ -63,8 +63,8 @@
|
||||
"@git.zone/tsbuild": "^2.2.0",
|
||||
"@git.zone/tsrun": "^1.3.3",
|
||||
"@git.zone/tstest": "^1.0.90",
|
||||
"@push.rocks/tapbundle": "^5.5.3",
|
||||
"@types/node": "^22.10.2"
|
||||
"@push.rocks/tapbundle": "^5.5.4",
|
||||
"@types/node": "^22.10.5"
|
||||
},
|
||||
"files": [
|
||||
"ts/**/*",
|
||||
|
1481
pnpm-lock.yaml
generated
1481
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartfile',
|
||||
version: '11.1.0',
|
||||
version: '11.1.1',
|
||||
description: 'Provides comprehensive tools for efficient file management in Node.js using TypeScript, including handling streams, virtual directories, and various file operations.'
|
||||
}
|
||||
|
91
ts/fs.ts
91
ts/fs.ts
@ -397,37 +397,57 @@ export const listFileTree = async (
|
||||
|
||||
/**
|
||||
* Watches for file stability before resolving the promise.
|
||||
* @param filePathArg The path of the file to monitor.
|
||||
* @param timeoutMs The maximum time to wait for the file to stabilize (in milliseconds). Default is 60 seconds.
|
||||
* @returns A promise that resolves when the file is stable or rejects on timeout or error.
|
||||
*/
|
||||
export const waitForFileToBeReady = (filePathArg: string): Promise<void> => {
|
||||
export const waitForFileToBeReady = (
|
||||
filePathArg: string,
|
||||
timeoutMs: number = 60000
|
||||
): Promise<void> => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let lastFileSize = -1;
|
||||
let fileIsStable = false;
|
||||
let isFileAvailable = false;
|
||||
|
||||
const startTime = Date.now();
|
||||
const fileDir = plugins.path.dirname(filePathArg);
|
||||
|
||||
const checkFileStability = async () => {
|
||||
let currentFileSize: number;
|
||||
const deferred = plugins.smartpromise.defer();
|
||||
plugins.fs.stat(filePathArg, (err, stats) => {
|
||||
if (err) {
|
||||
try {
|
||||
const stats: any = await plugins.smartpromise.fromCallback((cb) =>
|
||||
plugins.fs.stat(filePathArg, cb)
|
||||
);
|
||||
isFileAvailable = true;
|
||||
if (stats.size === lastFileSize) {
|
||||
fileIsStable = true;
|
||||
watcher.close();
|
||||
reject(err);
|
||||
return;
|
||||
} else {
|
||||
lastFileSize = stats.size;
|
||||
fileIsStable = false;
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
isFileAvailable = false; // File not available yet
|
||||
} else {
|
||||
throw err; // Propagate other errors
|
||||
}
|
||||
currentFileSize = stats.size;
|
||||
deferred.resolve();
|
||||
});
|
||||
await deferred.promise;
|
||||
if (currentFileSize === lastFileSize) {
|
||||
fileIsStable = true;
|
||||
await plugins.smartdelay.delayFor(100);
|
||||
resolve();
|
||||
}
|
||||
lastFileSize = currentFileSize;
|
||||
};
|
||||
|
||||
const watcher = plugins.fs.watch(filePathArg, (eventType, filename) => {
|
||||
if (eventType === 'change') {
|
||||
checkFileStability();
|
||||
const checkDirectory = async () => {
|
||||
try {
|
||||
await plugins.smartpromise.fromCallback((cb) =>
|
||||
plugins.fs.access(fileDir, plugins.fs.constants.R_OK, cb)
|
||||
);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const watcher = plugins.fs.watch(filePathArg, { persistent: true }, async () => {
|
||||
if (isFileAvailable && !fileIsStable) {
|
||||
await checkFileStability();
|
||||
}
|
||||
});
|
||||
|
||||
@ -436,13 +456,34 @@ export const waitForFileToBeReady = (filePathArg: string): Promise<void> => {
|
||||
reject(error);
|
||||
});
|
||||
|
||||
while (!fileIsStable) {
|
||||
await checkFileStability();
|
||||
if (!fileIsStable) {
|
||||
await plugins.smartdelay.delayFor(5000);
|
||||
try {
|
||||
while (!fileIsStable) {
|
||||
// Check for timeout
|
||||
if (Date.now() - startTime > timeoutMs) {
|
||||
watcher.close();
|
||||
reject(new Error(`Timeout waiting for file to be ready: ${filePathArg}`));
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure directory exists
|
||||
if (!await checkDirectory()) {
|
||||
await plugins.smartdelay.delayFor(500); // Wait and retry
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check file stability
|
||||
await checkFileStability();
|
||||
if (!fileIsStable) {
|
||||
await plugins.smartdelay.delayFor(1000); // Polling interval
|
||||
}
|
||||
}
|
||||
|
||||
watcher.close();
|
||||
resolve();
|
||||
} catch (err) {
|
||||
watcher.close();
|
||||
reject(err);
|
||||
}
|
||||
watcher.close();
|
||||
});
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user