@vzn/vx 0.0.196 → 0.0.197
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.
- package/package.json +5 -5
- package/src/cache/cache.ts +45 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.197",
|
|
4
4
|
"description": "A fast, correct task runner and build cache for JavaScript monorepos.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"node": ">=18"
|
|
18
18
|
},
|
|
19
19
|
"optionalDependencies": {
|
|
20
|
-
"@vzn/vx-linux-x64": "0.0.
|
|
21
|
-
"@vzn/vx-linux-arm64": "0.0.
|
|
22
|
-
"@vzn/vx-darwin-x64": "0.0.
|
|
23
|
-
"@vzn/vx-darwin-arm64": "0.0.
|
|
20
|
+
"@vzn/vx-linux-x64": "0.0.197",
|
|
21
|
+
"@vzn/vx-linux-arm64": "0.0.197",
|
|
22
|
+
"@vzn/vx-darwin-x64": "0.0.197",
|
|
23
|
+
"@vzn/vx-darwin-arm64": "0.0.197"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
package/src/cache/cache.ts
CHANGED
|
@@ -26,7 +26,16 @@
|
|
|
26
26
|
// layer speaks is `CacheLayer` in layer.ts; `plugin-host.ts` enforces it.
|
|
27
27
|
|
|
28
28
|
import { Database, type SQLQueryBindings } from 'bun:sqlite'
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
accessSync,
|
|
31
|
+
closeSync,
|
|
32
|
+
constants,
|
|
33
|
+
existsSync,
|
|
34
|
+
mkdirSync,
|
|
35
|
+
openSync,
|
|
36
|
+
renameSync,
|
|
37
|
+
writeFileSync,
|
|
38
|
+
} from 'node:fs'
|
|
30
39
|
import { readdir, rm, stat, unlink, writeFile } from 'node:fs/promises'
|
|
31
40
|
import path from 'node:path'
|
|
32
41
|
import { createTables } from './schema.js'
|
|
@@ -129,6 +138,26 @@ function unreadableIndexError(dbFile: string, err: unknown): UserError {
|
|
|
129
138
|
)
|
|
130
139
|
}
|
|
131
140
|
|
|
141
|
+
/**
|
|
142
|
+
* SQLite reports a descriptor it could not get as `SQLITE_CANTOPEN`, never
|
|
143
|
+
* `EMFILE`, so an open under a low `ulimit -n` reached the user as a bare
|
|
144
|
+
* `vx: SQLiteError: unable to open database file` (D's lead, A-56). One
|
|
145
|
+
* open of a file that exists says which it was.
|
|
146
|
+
*/
|
|
147
|
+
function outOfFdsAtOpen(dbFile: string, err: unknown): UserError | undefined {
|
|
148
|
+
const code = (err as { code?: unknown } | null)?.code
|
|
149
|
+
if (typeof code !== 'string' || !code.startsWith('SQLITE_CANTOPEN')) return undefined
|
|
150
|
+
try {
|
|
151
|
+
closeSync(openSync(process.execPath, 'r'))
|
|
152
|
+
return undefined
|
|
153
|
+
} catch (probe) {
|
|
154
|
+
if (!isOutOfFds(probe)) return undefined
|
|
155
|
+
return new UserError(
|
|
156
|
+
`the cache index ${dbFile} could not be opened (${(err as Error).message}) — ${OUT_OF_FDS_HINT}`,
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
132
161
|
/** Say once, on the channel the opener has, that an upgrade emptied the index. */
|
|
133
162
|
export function noteSchemaReset(cache: Cache, warn: (message: string) => void): void {
|
|
134
163
|
if (cache.formatChange !== null) {
|
|
@@ -527,7 +556,11 @@ export class Cache implements CacheLayer {
|
|
|
527
556
|
const absent = mode === 'inspect' && !existsSync(dbFile)
|
|
528
557
|
this.writeBlocked = absent ? 'no index there yet' : openCacheDir(cacheDir)
|
|
529
558
|
this.write = localPolicy.write && this.writeBlocked === null
|
|
530
|
-
|
|
559
|
+
try {
|
|
560
|
+
this.db = new Database(absent ? ':memory:' : dbFile, { create: true })
|
|
561
|
+
} catch (err) {
|
|
562
|
+
throw outOfFdsAtOpen(dbFile, err) ?? err
|
|
563
|
+
}
|
|
531
564
|
// busy_timeout makes concurrent writers wait for the lock instead of
|
|
532
565
|
// failing immediately with SQLITE_BUSY. Two parallel `vx run`
|
|
533
566
|
// invocations in CI is a normal pattern; without this the second one
|
|
@@ -544,7 +577,16 @@ export class Cache implements CacheLayer {
|
|
|
544
577
|
try {
|
|
545
578
|
return read()
|
|
546
579
|
} catch (err) {
|
|
547
|
-
if (!unreadableIndex(err))
|
|
580
|
+
if (!unreadableIndex(err)) {
|
|
581
|
+
const fds = outOfFdsAtOpen(dbFile, err)
|
|
582
|
+
if (fds === undefined) throw err
|
|
583
|
+
try {
|
|
584
|
+
closeDb(this.db)
|
|
585
|
+
} catch {
|
|
586
|
+
// The refusal is the error worth reporting.
|
|
587
|
+
}
|
|
588
|
+
throw fds
|
|
589
|
+
}
|
|
548
590
|
try {
|
|
549
591
|
closeDb(this.db)
|
|
550
592
|
} catch {
|