Files
orca/config/scripts/profile-state-worker-smoke.mjs
T
Neil acd298a263 feat(runtime): isolate the server behind a compatibility launcher (#26374)
* feat(runtime): isolate the server behind a compatibility launcher

* fix(runtime): preserve server crash exit semantics
2026-10-07 19:32:58 -07:00

163 lines
5.5 KiB
JavaScript

import { deepStrictEqual } from 'node:assert'
import { randomUUID } from 'node:crypto'
import { build } from 'esbuild'
import { mkdtempSync, rmSync } from 'node:fs'
import { createRequire } from 'node:module'
import { tmpdir } from 'node:os'
import { join, resolve } from 'node:path'
import { Worker } from 'node:worker_threads'
import { describeProcessFailure, runProcessSync } from './script-child-process.mjs'
import {
ORCAD_PROFILE_PREFLIGHT_FLAG,
parseOrcadProfilePreflight
} from '../../src/shared/orcad-profile-preflight.ts'
import { ORCAD_SERVER_ENTRY_FILENAME } from '../../src/shared/orcad-artifacts.ts'
import { NODE_RUNTIME_PIN } from '../../src/shared/node-runtime-pin.ts'
async function initializeFixture(directory, databasePath, profileId) {
const fixture = join(directory, 'initialize.cjs')
await build({
stdin: {
contents: `import { openProfileStateDatabase } from './src/main/persistence/profile-state/profile-state-database';
export function initialize(path, profileId) { openProfileStateDatabase(path, profileId).db.close() }`,
resolveDir: resolve(import.meta.dirname, '../..'),
sourcefile: 'profile-state-build-fixture.ts'
},
outfile: fixture,
bundle: true,
platform: 'node',
format: 'cjs',
logLevel: 'silent'
})
createRequire(import.meta.url)(fixture).initialize(databasePath, profileId)
}
function runWorker(entry, workerData, steps, timeoutMs) {
return new Promise((resolve, reject) => {
const worker = new Worker(entry, { workerData, execArgv: [] })
let received = 0
let failure
const stop = (error) => {
failure ??= error
void worker.terminate().catch((terminationError) => {
failure ??= terminationError
})
}
const timer = setTimeout(() => stop(new Error(`${entry} timed out`)), timeoutMs)
worker.on('message', (response) => {
if (failure) {
return
}
const step = steps[received]
if (!step) {
stop(new Error(`${entry} sent an unexpected response`))
return
}
try {
if (response?.ok === false) {
throw new Error(`${entry}: ${response.error?.message ?? response.error}`)
}
for (const [key, expected] of Object.entries(step.reply)) {
deepStrictEqual(response?.[key], expected, `${entry}: unexpected ${key}`)
}
received++
const next = steps[received]
if (next) {
worker.postMessage(next.request)
}
} catch (error) {
stop(error)
}
})
worker.on('error', (error) => {
failure ??= error
})
worker.once('exit', (code) => {
clearTimeout(timer)
if (failure || code !== 0 || received !== steps.length) {
reject(failure ?? new Error(`${entry} exited before completing its protocol (${code})`))
} else {
resolve()
}
})
})
}
/** Exercise the shipped entries and copied state before publishing their content version. */
export async function smokeProfileStateWorkers(outDir, { timeoutMs = 30_000, runtimePath } = {}) {
if (runtimePath) {
const nonce = randomUUID()
const result = runProcessSync({
program: runtimePath,
args: [join(outDir, ORCAD_SERVER_ENTRY_FILENAME), ORCAD_PROFILE_PREFLIGHT_FLAG, nonce],
env: { ...process.env, ORCA_BACKGROUND_LAUNCH: '1' },
timeoutMs,
maxOutputBytes: 64 * 1024
})
if (result.code !== 0 || result.timedOut || result.outputTruncated) {
throw new Error(
`Packaged profile runtime preflight failed: ${describeProcessFailure(result)}`
)
}
parseOrcadProfilePreflight(result.stdout, nonce, {
runtime: 'node',
runtimeVersion: NODE_RUNTIME_PIN.version
})
return
}
const directory = mkdtempSync(join(tmpdir(), 'orca-profile-worker-smoke-'))
const databasePath = join(directory, 'profile.db')
const targetPath = join(directory, 'backup.db')
const profileId = 'build-smoke'
const payload = JSON.stringify({ theme: 'dark', witness: 'saved \ud800 \u{1f419}' })
try {
await initializeFixture(directory, databasePath, profileId)
await runWorker(
join(outDir, 'profile-state-writer-worker-entry.js'),
{ databasePath, profileId, revision: 0 },
[
{ reply: { id: 0, ok: true, revision: 0 } },
{
request: {
id: 1,
command: 'write-complete',
replacements: [{ domain: 'settings', payload }]
},
reply: { id: 1, ok: true, revision: 1 }
},
{
request: { id: 2, command: 'close' },
reply: { id: 2, ok: true, revision: 1 }
}
],
timeoutMs
)
await runWorker(
join(outDir, 'profile-state-backup-worker-entry.js'),
{ databasePath, profileId, targetPath },
[{ reply: { ok: true } }],
timeoutMs
)
const { DatabaseSync } = process.getBuiltinModule('node:sqlite')
const database = new DatabaseSync(targetPath, { readOnly: true })
try {
deepStrictEqual(database.prepare('PRAGMA quick_check').get()['quick_check'], 'ok')
deepStrictEqual(
database
.prepare("SELECT payload FROM profile_state_documents WHERE domain = 'settings'")
.get()?.payload,
payload
)
deepStrictEqual(
database.prepare("SELECT value FROM profile_state_meta WHERE key = 'revision'").get()
?.value,
'1'
)
} finally {
database.close()
}
} finally {
rmSync(directory, { recursive: true, force: true })
}
}