mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-28 04:02:18 +01:00
fix(server): preserve live instruction locks
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
23b4420dbd
commit
c4e01860f7
2 files changed
+9
-11
No files matched your search
@@ -667,7 +667,7 @@ describe("agent instructions service", () => {
|
||||
});
|
||||
|
||||
it.skipIf(process.platform !== "linux")(
|
||||
"does not evict a live lock when process identity falls back to another scheme",
|
||||
"does not evict a live lock with a stale heartbeat when identity falls back to another scheme",
|
||||
async () => {
|
||||
const paperclipHome = await makeTempDir("paperclip-agent-instructions-marker-fallback-");
|
||||
cleanupDirs.add(paperclipHome);
|
||||
@@ -698,7 +698,10 @@ describe("agent instructions service", () => {
|
||||
})}\n`,
|
||||
"utf8",
|
||||
);
|
||||
await fs.writeFile(path.join(lockPath, `heartbeat-${token}`), "", "utf8");
|
||||
const heartbeatPath = path.join(lockPath, `heartbeat-${token}`);
|
||||
await fs.writeFile(heartbeatPath, "", "utf8");
|
||||
const staleHeartbeat = new Date(Date.now() - 60_000);
|
||||
await fs.utimes(heartbeatPath, staleHeartbeat, staleHeartbeat);
|
||||
|
||||
const materialization = svc.materializeManagedBundle(agent, { "AGENTS.md": "# Stock\n" });
|
||||
const firstOutcome = await Promise.race([
|
||||
|
||||
@@ -278,15 +278,11 @@ async function removeStaleManagedBundleLock(lockPath: string): Promise<boolean>
|
||||
ownerSnapshot = await fs.readFile(path.join(lockPath, "owner.json"), "utf8");
|
||||
const owner = JSON.parse(ownerSnapshot) as {
|
||||
pid?: unknown;
|
||||
token?: unknown;
|
||||
processStartMarker?: unknown;
|
||||
};
|
||||
const pid = typeof owner.pid === "number" && Number.isInteger(owner.pid) && owner.pid > 0
|
||||
? owner.pid
|
||||
: null;
|
||||
const token = typeof owner.token === "string" && /^[0-9a-f-]{36}$/i.test(owner.token)
|
||||
? owner.token
|
||||
: null;
|
||||
if (pid !== null && isProcessAlive(pid)) {
|
||||
const recordedStart = typeof owner.processStartMarker === "string"
|
||||
? owner.processStartMarker
|
||||
@@ -298,12 +294,11 @@ async function removeStaleManagedBundleLock(lockPath: string): Promise<boolean>
|
||||
&& processStartMarkersComparable(recordedStart, currentStart)
|
||||
) {
|
||||
shouldRemove = recordedStart !== currentStart;
|
||||
} else if (token) {
|
||||
shouldRemove = await managedBundleLockAgeMs(
|
||||
path.join(lockPath, `heartbeat-${token}`),
|
||||
) > MANAGED_BUNDLE_LOCK_STALE_MS;
|
||||
} else {
|
||||
shouldRemove = await managedBundleLockAgeMs(lockPath) > MANAGED_BUNDLE_LOCK_STALE_MS;
|
||||
// A delayed heartbeat does not prove that a live process has stopped
|
||||
// materializing. Only a comparable process-start marker can safely
|
||||
// distinguish a reused PID from the original owner.
|
||||
shouldRemove = false;
|
||||
}
|
||||
} else if (pid !== null) {
|
||||
shouldRemove = true;
|
||||
|
||||
Reference in new issue
Block a user