@wrongstack/persistence 0.298.3 → 0.300.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +23 -1
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -100,6 +100,15 @@ function createPersistencePrimitives(options = {}) {
100
100
  const staleMs = opts.staleMs ?? 3e4;
101
101
  const started = Date.now();
102
102
  let handle;
103
+ let attempt = 0;
104
+ let mkdirRetries = 0;
105
+ const retryAfterBackoff = async () => {
106
+ const elapsed = Date.now() - started;
107
+ if (elapsed >= timeoutMs) throw createLockTimeoutError({ targetPath, timeoutMs });
108
+ const backoffMs = Math.min(2 ** attempt, 100, timeoutMs - elapsed);
109
+ attempt++;
110
+ if (backoffMs > 0) await new Promise((resolve) => setTimeout(resolve, backoffMs));
111
+ };
103
112
  for (; ; ) {
104
113
  try {
105
114
  handle = await fs.open(lockPath, "wx");
@@ -114,6 +123,8 @@ function createPersistencePrimitives(options = {}) {
114
123
  const code = error.code;
115
124
  if (code === "ENOENT") {
116
125
  await fs.mkdir(dir, { recursive: true });
126
+ if (mkdirRetries++ === 0) continue;
127
+ await retryAfterBackoff();
117
128
  continue;
118
129
  }
119
130
  if (code !== "EEXIST" && code !== "EPERM") throw error;
@@ -124,9 +135,11 @@ function createPersistencePrimitives(options = {}) {
124
135
  if (recheck && recheck.mtimeMs === stat2.mtimeMs && Date.now() - recheck.mtimeMs > staleMs) {
125
136
  await fs.unlink(lockPath).catch(() => void 0);
126
137
  }
138
+ await retryAfterBackoff();
127
139
  continue;
128
140
  }
129
141
  } catch {
142
+ await retryAfterBackoff();
130
143
  continue;
131
144
  }
132
145
  const elapsed = Date.now() - started;
@@ -198,7 +211,16 @@ async function renameWithRetry(from, to) {
198
211
  return;
199
212
  } catch (error) {
200
213
  const code = error.code;
201
- if (!code || !TRANSIENT_RENAME_CODES.has(code) || attempt === delays.length) {
214
+ let transient = code !== void 0 && TRANSIENT_RENAME_CODES.has(code);
215
+ if (code === "ENOENT") {
216
+ try {
217
+ await fs.stat(from);
218
+ transient = true;
219
+ } catch {
220
+ transient = false;
221
+ }
222
+ }
223
+ if (!transient || attempt === delays.length) {
202
224
  if (attempt === delays.length) {
203
225
  process.emitWarning(
204
226
  `Windows rename retries exhausted for '${from}' \u2192 '${to}' (code=${code}). Write skipped \u2014 the caller will retry on the next cycle.`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/persistence",
3
- "version": "0.298.3",
3
+ "version": "0.300.0",
4
4
  "license": "MIT",
5
5
  "description": "Dependency-free filesystem persistence primitives shared across WrongStack packages.",
6
6
  "repository": {