feat(fs/Local): add stack traces to native fs methods
This commit is contained in:
parent
d27b6bd49d
commit
dbb9e4d60f
@ -1,13 +1,32 @@
|
|||||||
import df from '@sindresorhus/df'
|
import df from '@sindresorhus/df'
|
||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
|
import identity from 'lodash/identity.js'
|
||||||
import lockfile from 'proper-lockfile'
|
import lockfile from 'proper-lockfile'
|
||||||
import { fromEvent, retry } from 'promise-toolbox'
|
import { fromEvent, retry } from 'promise-toolbox'
|
||||||
|
|
||||||
import RemoteHandlerAbstract from './abstract'
|
import RemoteHandlerAbstract from './abstract'
|
||||||
|
|
||||||
|
// save current stack trace and add it to any rejected error
|
||||||
|
//
|
||||||
|
// This is especially useful when the resolution is separate from the initial
|
||||||
|
// call, which is often the case with RPC libs.
|
||||||
|
//
|
||||||
|
// There is a perf impact and it should be avoided in production.
|
||||||
|
async function addSyncStackTrace(promise) {
|
||||||
|
const stackContainer = new Error()
|
||||||
|
try {
|
||||||
|
return await promise
|
||||||
|
} catch (error) {
|
||||||
|
error.stack = stackContainer.stack
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default class LocalHandler extends RemoteHandlerAbstract {
|
export default class LocalHandler extends RemoteHandlerAbstract {
|
||||||
constructor(remote, opts = {}) {
|
constructor(remote, opts = {}) {
|
||||||
super(remote)
|
super(remote)
|
||||||
|
|
||||||
|
this._addSyncStackTrace = opts.syncStackTraces ?? true ? addSyncStackTrace : identity
|
||||||
this._retriesOnEagain = {
|
this._retriesOnEagain = {
|
||||||
delay: 1e3,
|
delay: 1e3,
|
||||||
retries: 9,
|
retries: 9,
|
||||||
@ -30,17 +49,17 @@ export default class LocalHandler extends RemoteHandlerAbstract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _closeFile(fd) {
|
async _closeFile(fd) {
|
||||||
return fs.close(fd)
|
return this._addSyncStackTrace(fs.close(fd))
|
||||||
}
|
}
|
||||||
|
|
||||||
async _copy(oldPath, newPath) {
|
async _copy(oldPath, newPath) {
|
||||||
return fs.copy(this._getFilePath(oldPath), this._getFilePath(newPath))
|
return this._addSyncStackTrace(fs.copy(this._getFilePath(oldPath), this._getFilePath(newPath)))
|
||||||
}
|
}
|
||||||
|
|
||||||
async _createReadStream(file, options) {
|
async _createReadStream(file, options) {
|
||||||
if (typeof file === 'string') {
|
if (typeof file === 'string') {
|
||||||
const stream = fs.createReadStream(this._getFilePath(file), options)
|
const stream = fs.createReadStream(this._getFilePath(file), options)
|
||||||
await fromEvent(stream, 'open')
|
await this._addSyncStackTrace(fromEvent(stream, 'open'))
|
||||||
return stream
|
return stream
|
||||||
}
|
}
|
||||||
return fs.createReadStream('', {
|
return fs.createReadStream('', {
|
||||||
@ -53,7 +72,7 @@ export default class LocalHandler extends RemoteHandlerAbstract {
|
|||||||
async _createWriteStream(file, options) {
|
async _createWriteStream(file, options) {
|
||||||
if (typeof file === 'string') {
|
if (typeof file === 'string') {
|
||||||
const stream = fs.createWriteStream(this._getFilePath(file), options)
|
const stream = fs.createWriteStream(this._getFilePath(file), options)
|
||||||
await fromEvent(stream, 'open')
|
await this._addSyncStackTrace(fromEvent(stream, 'open'))
|
||||||
return stream
|
return stream
|
||||||
}
|
}
|
||||||
return fs.createWriteStream('', {
|
return fs.createWriteStream('', {
|
||||||
@ -79,12 +98,12 @@ export default class LocalHandler extends RemoteHandlerAbstract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _getSize(file) {
|
async _getSize(file) {
|
||||||
const stats = await fs.stat(this._getFilePath(typeof file === 'string' ? file : file.path))
|
const stats = await this._addSyncStackTrace(fs.stat(this._getFilePath(typeof file === 'string' ? file : file.path)))
|
||||||
return stats.size
|
return stats.size
|
||||||
}
|
}
|
||||||
|
|
||||||
async _list(dir) {
|
async _list(dir) {
|
||||||
return fs.readdir(this._getFilePath(dir))
|
return this._addSyncStackTrace(fs.readdir(this._getFilePath(dir)))
|
||||||
}
|
}
|
||||||
|
|
||||||
_lock(path) {
|
_lock(path) {
|
||||||
@ -92,58 +111,60 @@ export default class LocalHandler extends RemoteHandlerAbstract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_mkdir(dir, { mode }) {
|
_mkdir(dir, { mode }) {
|
||||||
return fs.mkdir(this._getFilePath(dir), { mode })
|
return this._addSyncStackTrace(fs.mkdir(this._getFilePath(dir), { mode }))
|
||||||
}
|
}
|
||||||
|
|
||||||
async _openFile(path, flags) {
|
async _openFile(path, flags) {
|
||||||
return fs.open(this._getFilePath(path), flags)
|
return this._addSyncStackTrace(fs.open(this._getFilePath(path), flags))
|
||||||
}
|
}
|
||||||
|
|
||||||
async _read(file, buffer, position) {
|
async _read(file, buffer, position) {
|
||||||
const needsClose = typeof file === 'string'
|
const needsClose = typeof file === 'string'
|
||||||
file = needsClose ? await fs.open(this._getFilePath(file), 'r') : file.fd
|
file = needsClose ? await this._addSyncStackTrace(fs.open(this._getFilePath(file), 'r')) : file.fd
|
||||||
try {
|
try {
|
||||||
return await fs.read(file, buffer, 0, buffer.length, position === undefined ? null : position)
|
return await this._addSyncStackTrace(
|
||||||
|
fs.read(file, buffer, 0, buffer.length, position === undefined ? null : position)
|
||||||
|
)
|
||||||
} finally {
|
} finally {
|
||||||
if (needsClose) {
|
if (needsClose) {
|
||||||
await fs.close(file)
|
await this._addSyncStackTrace(fs.close(file))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _readFile(file, options) {
|
async _readFile(file, options) {
|
||||||
const filePath = this._getFilePath(file)
|
const filePath = this._getFilePath(file)
|
||||||
return await retry(() => fs.readFile(filePath, options), this._retriesOnEagain)
|
return await this._addSyncStackTrace(retry(() => fs.readFile(filePath, options), this._retriesOnEagain))
|
||||||
}
|
}
|
||||||
|
|
||||||
async _rename(oldPath, newPath) {
|
async _rename(oldPath, newPath) {
|
||||||
return fs.rename(this._getFilePath(oldPath), this._getFilePath(newPath))
|
return this._addSyncStackTrace(fs.rename(this._getFilePath(oldPath), this._getFilePath(newPath)))
|
||||||
}
|
}
|
||||||
|
|
||||||
async _rmdir(dir) {
|
async _rmdir(dir) {
|
||||||
return fs.rmdir(this._getFilePath(dir))
|
return this._addSyncStackTrace(fs.rmdir(this._getFilePath(dir)))
|
||||||
}
|
}
|
||||||
|
|
||||||
async _sync() {
|
async _sync() {
|
||||||
const path = this._getRealPath('/')
|
const path = this._getRealPath('/')
|
||||||
await fs.ensureDir(path)
|
await this._addSyncStackTrace(fs.ensureDir(path))
|
||||||
await fs.access(path, fs.R_OK | fs.W_OK)
|
await this._addSyncStackTrace(fs.access(path, fs.R_OK | fs.W_OK))
|
||||||
}
|
}
|
||||||
|
|
||||||
_truncate(file, len) {
|
_truncate(file, len) {
|
||||||
return fs.truncate(this._getFilePath(file), len)
|
return this._addSyncStackTrace(fs.truncate(this._getFilePath(file), len))
|
||||||
}
|
}
|
||||||
|
|
||||||
async _unlink(file) {
|
async _unlink(file) {
|
||||||
const filePath = this._getFilePath(file)
|
const filePath = this._getFilePath(file)
|
||||||
return await retry(() => fs.unlink(filePath), this._retriesOnEagain)
|
return await this._addSyncStackTrace(retry(() => fs.unlink(filePath), this._retriesOnEagain))
|
||||||
}
|
}
|
||||||
|
|
||||||
_writeFd(file, buffer, position) {
|
_writeFd(file, buffer, position) {
|
||||||
return fs.write(file.fd, buffer, 0, buffer.length, position)
|
return this._addSyncStackTrace(fs.write(file.fd, buffer, 0, buffer.length, position))
|
||||||
}
|
}
|
||||||
|
|
||||||
_writeFile(file, data, { flags }) {
|
_writeFile(file, data, { flags }) {
|
||||||
return fs.writeFile(this._getFilePath(file), data, { flag: flags })
|
return this._addSyncStackTrace(fs.writeFile(this._getFilePath(file), data, { flag: flags }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
<!--packages-start-->
|
<!--packages-start-->
|
||||||
|
|
||||||
|
- @xen-orchestra/fs minor
|
||||||
- vhd-lib major
|
- vhd-lib major
|
||||||
|
|
||||||
<!--packages-end-->
|
<!--packages-end-->
|
||||||
|
Loading…
Reference in New Issue
Block a user