refactor(boot): use addon-managed native cache
This commit is contained in:
1 parent
d4350442e8
commit
c3a66d9cd2
6 files changed
+11
-106
No files matched your search
@@ -963,19 +963,13 @@ export function installProfileResolution(
|
||||
* Publish one generation for Harness-owned Workers.
|
||||
* @param generation - complete package table and profile scope.
|
||||
* @param behavior - enforce or verify the generation in newly created Workers.
|
||||
* @param nativeCacheDir - private physical directory used to load the native adapter in a Worker.
|
||||
* @returns a disposer restoring the previous thread environment data.
|
||||
*/
|
||||
export function registerWorkerResolution(
|
||||
generation: ProfileResolutionGeneration,
|
||||
behavior: ProfileResolutionBehavior = 'enforce',
|
||||
nativeCacheDir?: string,
|
||||
): () => void {
|
||||
const previous = getEnvironmentData(WORKER_RESOLUTION_KEY)
|
||||
setEnvironmentData(WORKER_RESOLUTION_KEY, {
|
||||
generation,
|
||||
behavior,
|
||||
...(nativeCacheDir === undefined ? {} : { nativeCacheDir }),
|
||||
})
|
||||
setEnvironmentData(WORKER_RESOLUTION_KEY, { generation, behavior })
|
||||
return () => { setEnvironmentData(WORKER_RESOLUTION_KEY, previous) }
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
/** Package metadata resolved through one profile resolution registration. */
|
||||
|
||||
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs'
|
||||
import { rm } from 'node:fs/promises'
|
||||
import { existsSync, readFileSync } from 'node:fs'
|
||||
import { createRequire } from 'node:module'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { Service, type Context } from '@deepseek-ai/cordis'
|
||||
import {
|
||||
@@ -64,47 +62,18 @@ export class PluginPackages extends Service {
|
||||
private packages = new Map<string, PluginPackage | undefined>()
|
||||
private readonly resolver: ProfileResolutionRegistration | undefined
|
||||
private readonly behavior: ProfileResolutionBehavior
|
||||
private readonly nativeCacheDir: string | undefined
|
||||
private disposeWorkerResolution: (() => void) | undefined
|
||||
|
||||
constructor(ctx: Context, config: PluginPackagesConfig = {}) {
|
||||
super(ctx, 'pluginPackages')
|
||||
this.behavior = config.behavior ?? 'enforce'
|
||||
/* v8 ignore start -- Linux coverage cannot enter the Windows native-cache lifecycle. */
|
||||
this.nativeCacheDir = config.generation !== undefined && process.platform === 'win32'
|
||||
? mkdtempSync(join(tmpdir(), 'dsh-profile-resolution-native-'))
|
||||
: undefined
|
||||
/* v8 ignore stop */
|
||||
if (config.generation === undefined) return
|
||||
let resolver: ProfileResolutionRegistration
|
||||
try {
|
||||
resolver = installProfileResolution(config.generation, this.behavior)
|
||||
} catch (error) {
|
||||
/* v8 ignore next -- only an unsupported Node Internal can fail before service publication. */
|
||||
if (this.nativeCacheDir !== undefined) rmSync(this.nativeCacheDir, { recursive: true, force: true })
|
||||
/* v8 ignore next -- the unsupported-Node failure is covered by the external version matrix. */
|
||||
throw error
|
||||
}
|
||||
this.disposeWorkerResolution = registerWorkerResolution(
|
||||
config.generation, this.behavior, this.nativeCacheDir,
|
||||
)
|
||||
const resolver = installProfileResolution(config.generation, this.behavior)
|
||||
this.disposeWorkerResolution = registerWorkerResolution(config.generation, this.behavior)
|
||||
this.resolver = resolver
|
||||
ctx.effect(() => async () => {
|
||||
ctx.effect(() => () => {
|
||||
this.disposeWorkerResolution?.()
|
||||
resolver.dispose()
|
||||
/* v8 ignore start -- Linux coverage cannot enter the Windows native-cache lifecycle. */
|
||||
if (this.nativeCacheDir !== undefined) {
|
||||
try {
|
||||
await rm(this.nativeCacheDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 })
|
||||
} catch (error) {
|
||||
const code = (error as NodeJS.ErrnoException).code
|
||||
if (code !== 'EBUSY' && code !== 'EPERM' && code !== 'ENOTEMPTY') throw error
|
||||
ctx.logger.warn(
|
||||
`profile package resolution: native cache ${this.nativeCacheDir} remains locked after Worker teardown`,
|
||||
)
|
||||
}
|
||||
}
|
||||
/* v8 ignore stop */
|
||||
}, 'profile package resolution')
|
||||
}
|
||||
|
||||
@@ -117,7 +86,7 @@ export class PluginPackages extends Service {
|
||||
this.resolver.replace(generation)
|
||||
this.packages = new Map()
|
||||
this.disposeWorkerResolution?.()
|
||||
this.disposeWorkerResolution = registerWorkerResolution(generation, this.behavior, this.nativeCacheDir)
|
||||
this.disposeWorkerResolution = registerWorkerResolution(generation, this.behavior)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,15 +9,5 @@ const registration = getEnvironmentData(
|
||||
) as {
|
||||
generation: ProfileResolutionGeneration
|
||||
behavior: ProfileResolutionBehavior
|
||||
nativeCacheDir?: string
|
||||
} | undefined
|
||||
if (registration !== undefined) {
|
||||
const previous = process.env.NARB_NATIVE_CACHE_DIR
|
||||
if (registration.nativeCacheDir !== undefined) process.env.NARB_NATIVE_CACHE_DIR = registration.nativeCacheDir
|
||||
try {
|
||||
installProfileResolution(registration.generation, registration.behavior)
|
||||
} finally {
|
||||
if (previous === undefined) delete process.env.NARB_NATIVE_CACHE_DIR
|
||||
else process.env.NARB_NATIVE_CACHE_DIR = previous
|
||||
}
|
||||
}
|
||||
if (registration !== undefined) installProfileResolution(registration.generation, registration.behavior)
|
||||
@@ -1,6 +1,6 @@
|
||||
/** Package metadata queries share the active profile resolution generation. */
|
||||
|
||||
import { existsSync, mkdirSync, mkdtempSync, realpathSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'
|
||||
import { mkdirSync, mkdtempSync, realpathSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'
|
||||
import { createRequire } from 'node:module'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { dirname, join } from 'node:path'
|
||||
@@ -172,15 +172,8 @@ describe('profile package metadata service', () => {
|
||||
const initialWorkerData = getEnvironmentData(key) as {
|
||||
generation: ProfileResolutionGeneration
|
||||
behavior: string
|
||||
nativeCacheDir?: string
|
||||
}
|
||||
expect(initialWorkerData).toMatchObject({ generation: initial, behavior: 'verify' })
|
||||
if (process.platform === 'win32') {
|
||||
expect(initialWorkerData.nativeCacheDir).toEqual(expect.any(String))
|
||||
expect(existsSync(initialWorkerData.nativeCacheDir as string)).toBe(true)
|
||||
} else {
|
||||
expect(initialWorkerData).not.toHaveProperty('nativeCacheDir')
|
||||
}
|
||||
expect(initialWorkerData).toEqual({ generation: initial, behavior: 'verify' })
|
||||
|
||||
const added = join(root, 'added')
|
||||
const addedAnchor = pkg(added, '2.0.0', 'added-metadata')
|
||||
@@ -200,7 +193,6 @@ describe('profile package metadata service', () => {
|
||||
expect(getEnvironmentData(key)).toEqual({
|
||||
generation: next,
|
||||
behavior: 'verify',
|
||||
...(initialWorkerData.nativeCacheDir === undefined ? {} : { nativeCacheDir: initialWorkerData.nativeCacheDir }),
|
||||
})
|
||||
expect(ctx.pluginPackages.packageOf(
|
||||
'added-metadata', pathToFileURL(join(profileDir, 'entry.mjs')).href,
|
||||
@@ -209,8 +201,5 @@ describe('profile package metadata service', () => {
|
||||
await ctx.fiber.dispose()
|
||||
contexts.pop()
|
||||
expect(getEnvironmentData(key)).toBe(previous)
|
||||
if (initialWorkerData.nativeCacheDir !== undefined) {
|
||||
expect(existsSync(initialWorkerData.nativeCacheDir)).toBe(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -1,19 +1,16 @@
|
||||
/** Worker bootstrap installs only the generation inherited from its parent. */
|
||||
|
||||
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
|
||||
import { beforeEach, expect, it, vi } from 'vitest'
|
||||
import type { ProfileResolutionGeneration } from '../src/profile.ts'
|
||||
|
||||
const harness = vi.hoisted(() => ({
|
||||
data: undefined as {
|
||||
generation: ProfileResolutionGeneration
|
||||
behavior: 'enforce' | 'verify'
|
||||
nativeCacheDir?: string
|
||||
} | undefined,
|
||||
install: vi.fn(),
|
||||
}))
|
||||
|
||||
let previousNativeCacheDir: string | undefined
|
||||
|
||||
vi.mock('node:worker_threads', () => ({
|
||||
getEnvironmentData: () => harness.data,
|
||||
}))
|
||||
@@ -23,18 +20,11 @@ vi.mock('../src/profile-resolution/resolver.ts', () => ({
|
||||
}))
|
||||
|
||||
beforeEach(() => {
|
||||
previousNativeCacheDir = process.env.NARB_NATIVE_CACHE_DIR
|
||||
delete process.env.NARB_NATIVE_CACHE_DIR
|
||||
harness.data = undefined
|
||||
harness.install.mockReset()
|
||||
vi.resetModules()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
if (previousNativeCacheDir === undefined) delete process.env.NARB_NATIVE_CACHE_DIR
|
||||
else process.env.NARB_NATIVE_CACHE_DIR = previousNativeCacheDir
|
||||
})
|
||||
|
||||
it('does nothing without inherited profile resolution data', async () => {
|
||||
await import('../src/profile-resolution/worker-bootstrap.ts')
|
||||
expect(harness.install).not.toHaveBeenCalled()
|
||||
@@ -47,24 +37,7 @@ it('installs the inherited generation and behavior', async () => {
|
||||
localPackageNames: [],
|
||||
entries: [],
|
||||
}
|
||||
harness.data = { generation, behavior: 'verify', nativeCacheDir: '/private/native-cache' }
|
||||
harness.install.mockImplementation(() => {
|
||||
expect(process.env.NARB_NATIVE_CACHE_DIR).toBe('/private/native-cache')
|
||||
})
|
||||
harness.data = { generation, behavior: 'verify' }
|
||||
await import('../src/profile-resolution/worker-bootstrap.ts')
|
||||
expect(harness.install).toHaveBeenCalledWith(generation, 'verify')
|
||||
expect(process.env.NARB_NATIVE_CACHE_DIR).toBeUndefined()
|
||||
})
|
||||
|
||||
it('restores an existing native-cache environment value after bootstrap', async () => {
|
||||
const generation: ProfileResolutionGeneration = {
|
||||
profilesDir: '/profiles',
|
||||
profileDir: '/profiles/test',
|
||||
localPackageNames: [],
|
||||
entries: [],
|
||||
}
|
||||
process.env.NARB_NATIVE_CACHE_DIR = '/existing/native-cache'
|
||||
harness.data = { generation, behavior: 'enforce' }
|
||||
await import('../src/profile-resolution/worker-bootstrap.ts')
|
||||
expect(process.env.NARB_NATIVE_CACHE_DIR).toBe('/existing/native-cache')
|
||||
})
|
||||
@@ -1505,16 +1505,6 @@ describe('profile resolution generation', { concurrent: false }, () => {
|
||||
dispose()
|
||||
}
|
||||
expect(getEnvironmentData(key)).toBe(previous)
|
||||
|
||||
const disposeWithCache = registerWorkerResolution(generation, 'enforce', '/private/native-cache')
|
||||
try {
|
||||
expect(getEnvironmentData(key)).toEqual({
|
||||
generation, behavior: 'enforce', nativeCacheDir: '/private/native-cache',
|
||||
})
|
||||
} finally {
|
||||
disposeWithCache()
|
||||
}
|
||||
expect(getEnvironmentData(key)).toBe(previous)
|
||||
})
|
||||
|
||||
it('restores CommonJS resolution when the registration is disposed', async () => {
|
||||
|
||||
Reference in new issue
Block a user