grix-connector
Version:
Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.
3 lines (2 loc) • 1.72 kB
JavaScript
import{openSync as w,closeSync as S,existsSync as D,readFileSync as f,unlinkSync as s,writeSync as k}from"node:fs";import{mkdir as h}from"node:fs/promises";import d from"node:path";import o from"node:process";import{isProcessRunning as i}from"../service/process-control.js";function l(r){try{const n=JSON.parse(r);if(typeof n?.pid=="number"&&typeof n.acquired_at=="number")return n}catch{}return null}function p(r){if(!D(r))return null;try{return l(f(r,"utf8"))}catch{return null}}function $(r){const n=p(r);return n!==null&&i(n.pid)}function y(r){const n=new Int32Array(new SharedArrayBuffer(4));Atomics.wait(n,0,0,r)}function x(r){if(r<=0||r===o.pid)return!0;try{o.kill(r,"SIGTERM")}catch{return!0}const n=Date.now()+3e3;for(;Date.now()<n;){if(!i(r))return!0;y(100)}try{o.kill(r,"SIGKILL")}catch{}const c=Date.now()+1e3;for(;Date.now()<c;){if(!i(r))return!0;y(50)}return!i(r)}async function b(r,n,c=2){await h(d.dirname(r),{recursive:!0});const a={pid:o.pid,acquired_at:Date.now(),root_dir:d.resolve(n)},m=`${JSON.stringify(a,null,2)}
`;for(let u=0;u<=c;u+=1)try{const e=w(r,"wx");try{k(e,m)}finally{S(e)}return a}catch(e){if(!(e instanceof Error)||e.code!=="EEXIST")throw e;const t=l(f(r,"utf8"));if(t&&i(t.pid)){if(t.pid===o.pid)throw new Error(`daemon already running (pid ${t.pid}, acquired at ${new Date(t.acquired_at).toISOString()})`);if(!x(t.pid))throw new Error(`\u65E0\u6CD5\u7EC8\u6B62\u8001\u8FDB\u7A0B (pid ${t.pid})\uFF0C\u8BF7\u624B\u52A8\u5904\u7406`)}try{s(r)}catch{}}throw new Error("failed to acquire daemon lock after retries")}async function A(r){const n=p(r);if(n&&n.pid===o.pid)try{s(r)}catch{}}export{b as acquireDaemonLock,$ as isDaemonLocked,p as readDaemonLock,A as releaseDaemonLock};