mirror of
https://github.com/stablyai/orca.git
synced 2026-10-17 00:03:08 +00:00
fix(build): address WSL runtime review findings
This commit is contained in:
@@ -51,29 +51,31 @@ function currentProcessStartToken() {
|
||||
try {
|
||||
if (process.platform === 'linux') {
|
||||
const contents = readFileSync(`/proc/${process.pid}/stat`, 'utf8')
|
||||
cachedProcessStartToken = contents.slice(contents.lastIndexOf(') ') + 2).split(' ')[19]
|
||||
cachedProcessStartToken =
|
||||
contents.slice(contents.lastIndexOf(') ') + 2).split(' ')[19] || null
|
||||
} else if (process.platform === 'win32') {
|
||||
cachedProcessStartToken = execFileSync(
|
||||
'powershell.exe',
|
||||
[
|
||||
'-NoProfile',
|
||||
'-NonInteractive',
|
||||
'-Command',
|
||||
`(Get-Process -Id ${process.pid} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`
|
||||
],
|
||||
{ encoding: 'utf8', timeout: 2_000, windowsHide: true }
|
||||
).trim()
|
||||
cachedProcessStartToken =
|
||||
execFileSync(
|
||||
'powershell.exe',
|
||||
[
|
||||
'-NoProfile',
|
||||
'-NonInteractive',
|
||||
'-Command',
|
||||
`(Get-Process -Id ${process.pid} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`
|
||||
],
|
||||
{ encoding: 'utf8', timeout: 2_000, windowsHide: true }
|
||||
).trim() || null
|
||||
} else {
|
||||
cachedProcessStartToken = execFileSync(
|
||||
'ps',
|
||||
['-o', 'lstart=', '-p', String(process.pid)],
|
||||
{ encoding: 'utf8', timeout: 2_000 }
|
||||
).trim()
|
||||
cachedProcessStartToken =
|
||||
execFileSync('ps', ['-o', 'lstart=', '-p', String(process.pid)], {
|
||||
encoding: 'utf8',
|
||||
timeout: 2_000
|
||||
}).trim() || null
|
||||
}
|
||||
} catch {
|
||||
cachedProcessStartToken = null
|
||||
}
|
||||
return cachedProcessStartToken || null
|
||||
return cachedProcessStartToken
|
||||
}
|
||||
|
||||
function parseWslRuntimeBuildSource(output) {
|
||||
@@ -83,8 +85,7 @@ function parseWslRuntimeBuildSource(output) {
|
||||
function parseWslRuntimePreparationOutput(output) {
|
||||
const text = Buffer.isBuffer(output) ? output.toString('utf8') : String(output ?? '')
|
||||
const lines = text.split(/\r?\n/)
|
||||
const value = (name) =>
|
||||
lines.find((line) => line.startsWith(`${name}=`))?.slice(name.length + 1)
|
||||
const value = (name) => lines.find((line) => line.startsWith(`${name}=`))?.slice(name.length + 1)
|
||||
const source = value('ORCA_WSL_WATCHER_BUILD_SOURCE')
|
||||
const lease = value('ORCA_WSL_WATCHER_BUILD_LEASE')
|
||||
if (!source || !lease) {
|
||||
|
||||
@@ -199,9 +199,11 @@ async function activeLeaseVersions(buildsDir, names, operations, options) {
|
||||
let owner
|
||||
let modifiedAt = 0
|
||||
try {
|
||||
owner = JSON.parse(await operations.readFile(join(leasePath, 'owner.json'), 'utf8'))
|
||||
modifiedAt = (await operations.stat(leasePath)).mtimeMs
|
||||
} catch {}
|
||||
try {
|
||||
owner = JSON.parse(await operations.readFile(join(leasePath, 'owner.json'), 'utf8'))
|
||||
} catch {}
|
||||
const alive = Number.isSafeInteger(owner?.pid) ? await options.ownerIsAlive(owner) : null
|
||||
if (
|
||||
alive === true ||
|
||||
|
||||
@@ -14,6 +14,43 @@ import {
|
||||
const execFileAsync = promisify(execFile)
|
||||
|
||||
describe('immutable WSL runtime build retention', () => {
|
||||
it('preserves a fresh lease while its owner metadata is being published', async () => {
|
||||
const root = await mkdtemp(join(tmpdir(), 'orca-wsl-build-pending-lease-'))
|
||||
const output = join(root, 'out', 'wsl-watcher')
|
||||
const version = 'b'.repeat(20)
|
||||
const buildsDir = `${output}.builds`
|
||||
const build = join(buildsDir, version)
|
||||
const lease = join(buildsDir, `${version}.lease-pending`)
|
||||
try {
|
||||
await mkdir(build, { recursive: true })
|
||||
await mkdir(lease)
|
||||
await utimes(lease, new Date(99_500), new Date(99_500))
|
||||
|
||||
await pruneImmutableRuntimeBuilds(output, {
|
||||
maxCompletedBuilds: 0,
|
||||
minRecentBuilds: 0,
|
||||
maxBuildAgeMs: 0,
|
||||
unknownLeaseAgeMs: 1_000,
|
||||
now: () => 100_000
|
||||
})
|
||||
expect(await readdir(buildsDir)).toEqual(
|
||||
expect.arrayContaining([version, `${version}.lease-pending`])
|
||||
)
|
||||
|
||||
await pruneImmutableRuntimeBuilds(output, {
|
||||
maxCompletedBuilds: 0,
|
||||
minRecentBuilds: 0,
|
||||
maxBuildAgeMs: 0,
|
||||
unknownLeaseAgeMs: 1_000,
|
||||
now: () => 101_000
|
||||
})
|
||||
expect(await readdir(buildsDir)).not.toContain(version)
|
||||
expect(await readdir(buildsDir)).not.toContain(`${version}.lease-pending`)
|
||||
} finally {
|
||||
await rm(root, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
it('preserves current, recent, and actively leased builds while bounding completed versions', async () => {
|
||||
const root = await mkdtemp(join(tmpdir(), 'orca-wsl-build-retention-'))
|
||||
const output = join(root, 'out', 'wsl-watcher')
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { execFile } from 'node:child_process'
|
||||
import { mkdir, readFile, rename, rm, stat, writeFile } from 'node:fs/promises'
|
||||
import { join } from 'node:path'
|
||||
import { promisify } from 'node:util'
|
||||
|
||||
const DEFAULT_HEARTBEAT_INTERVAL_MS = 1_000
|
||||
@@ -21,7 +22,7 @@ function delay(milliseconds) {
|
||||
|
||||
async function readOwner(lockPath, operations) {
|
||||
try {
|
||||
const parsed = JSON.parse(await operations.readFile(`${lockPath}/owner.json`, 'utf8'))
|
||||
const parsed = JSON.parse(await operations.readFile(join(lockPath, 'owner.json'), 'utf8'))
|
||||
return typeof parsed?.token === 'string' && Number.isSafeInteger(parsed.pid) ? parsed : null
|
||||
} catch {
|
||||
return null
|
||||
@@ -78,7 +79,7 @@ async function defaultOwnerIsAlive(owner) {
|
||||
|
||||
async function heartbeatIsStale(lockPath, operations, now, staleMs) {
|
||||
try {
|
||||
const heartbeat = await operations.stat(`${lockPath}/heartbeat`)
|
||||
const heartbeat = await operations.stat(join(lockPath, 'heartbeat'))
|
||||
return now() - heartbeat.mtimeMs >= staleMs
|
||||
} catch {
|
||||
try {
|
||||
@@ -125,7 +126,7 @@ function startHeartbeat(lockPath, owner, operations, intervalMs) {
|
||||
const tick = async () => {
|
||||
const current = await readOwner(lockPath, operations)
|
||||
if (current?.token === owner.token) {
|
||||
await operations.writeFile(`${lockPath}/heartbeat`, owner.token).catch(() => undefined)
|
||||
await operations.writeFile(join(lockPath, 'heartbeat'), owner.token).catch(() => undefined)
|
||||
}
|
||||
}
|
||||
const timer = setInterval(() => void tick(), intervalMs)
|
||||
@@ -163,8 +164,8 @@ export async function withRuntimePublicationLock(
|
||||
try {
|
||||
await operations.mkdir(lockPath)
|
||||
try {
|
||||
await operations.writeFile(`${lockPath}/owner.json`, JSON.stringify(owner))
|
||||
await operations.writeFile(`${lockPath}/heartbeat`, token)
|
||||
await operations.writeFile(join(lockPath, 'owner.json'), JSON.stringify(owner))
|
||||
await operations.writeFile(join(lockPath, 'heartbeat'), token)
|
||||
} catch (error) {
|
||||
await operations.rm(lockPath, { recursive: true, force: true })
|
||||
throw error
|
||||
|
||||
@@ -7,6 +7,7 @@ export function createWatcherBindingWatchdog(
|
||||
timeoutMs: number
|
||||
): WatcherBindingWatchdog {
|
||||
let recycling = false
|
||||
// Why: concurrent native timeouts must trigger only one host recycle.
|
||||
const recycleHost = (operation: string): void => {
|
||||
if (recycling) {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user