gitnexus 1.6.12-rc.12 → 1.6.12-rc.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ import path from 'node:path';
4
4
  import { execFileSync } from 'node:child_process';
5
5
  import { acquireFileLock, FileLockBusyError } from '../../storage/file-lock.js';
6
6
  import { getGlobalDir } from '../../storage/repo-manager.js';
7
- import { isProcessAlive, readProcessStartTime } from '../../utils/process-identity.js';
7
+ import { isProcessAlive, readProcessStartTimeCached } from '../../utils/process-identity.js';
8
8
  import { loadAutoSyncConfig } from './config.js';
9
9
  import { runAutoSyncOnce } from './runner.js';
10
10
  import { getAutoSyncMutexPath, getAutoSyncWatchDir } from './state.js';
@@ -488,7 +488,7 @@ function resolveWatchDeps(deps = {}) {
488
488
  return undefined;
489
489
  }
490
490
  }),
491
- readProcessStartTime: deps.readProcessStartTime ?? readProcessStartTime,
491
+ readProcessStartTime: deps.readProcessStartTime ?? readProcessStartTimeCached,
492
492
  sleep: deps.sleep ??
493
493
  ((ms) => new Promise((resolve) => {
494
494
  setTimeout(resolve, ms);
@@ -3,7 +3,7 @@ import fs from 'node:fs/promises';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { setTimeout as sleep } from 'node:timers/promises';
6
- import { isProcessAlive, readProcessStartTime } from '../utils/process-identity.js';
6
+ import { isProcessAlive, readProcessStartTimeCached } from '../utils/process-identity.js';
7
7
  const HOSTNAME = os.hostname();
8
8
  export class FileLockBusyError extends Error {
9
9
  lockPath;
@@ -22,7 +22,9 @@ export async function acquireFileLock(lockPath, options = {}) {
22
22
  const owner = {
23
23
  pid,
24
24
  ownerId: crypto.randomUUID(),
25
- processStartTime: options.processStartTime ?? (options.readProcessStartTime ?? readProcessStartTime)(pid) ?? '',
25
+ processStartTime: options.processStartTime ??
26
+ (options.readProcessStartTime ?? readProcessStartTimeCached)(pid) ??
27
+ '',
26
28
  hostname: options.hostname ?? HOSTNAME,
27
29
  };
28
30
  if (!owner.processStartTime) {
@@ -40,7 +42,7 @@ export async function acquireFileLock(lockPath, options = {}) {
40
42
  catch (error) {
41
43
  if (!(await isLockConflict(error, resolvedPath)))
42
44
  throw error;
43
- if (await reclaimStaleLock(resolvedPath, owner, options.isProcessAlive ?? isProcessAlive, options.readProcessStartTime ?? readProcessStartTime)) {
45
+ if (await reclaimStaleLock(resolvedPath, owner, options.isProcessAlive ?? isProcessAlive, options.readProcessStartTime ?? readProcessStartTimeCached)) {
44
46
  continue;
45
47
  }
46
48
  if (attempt >= retries)
@@ -1,2 +1,15 @@
1
1
  export declare function isProcessAlive(pid: number): boolean;
2
2
  export declare function readProcessStartTime(pid: number): string | undefined;
3
+ /**
4
+ * `readProcessStartTime`, except this process's own start time is probed once.
5
+ * It cannot change while we are running, and every `acquireFileLock` — plus
6
+ * each retry attempt and each stale-lock reclaim guard — stamps the owner file
7
+ * with it. On Windows that probe is a `powershell.exe` spawn and a WMI query,
8
+ * so a process taking several locks pays it several times for one constant.
9
+ *
10
+ * A foreign pid is never cached: that process can exit and its pid can be
11
+ * reused, which is the very thing the stamp exists to detect. A failed probe
12
+ * is not cached either — one transient failure would otherwise leave the
13
+ * process unable to take a lock for its whole lifetime.
14
+ */
15
+ export declare function readProcessStartTimeCached(pid: number): string | undefined;
@@ -33,3 +33,21 @@ export function readProcessStartTime(pid) {
33
33
  return undefined;
34
34
  }
35
35
  }
36
+ let ownStartTime;
37
+ /**
38
+ * `readProcessStartTime`, except this process's own start time is probed once.
39
+ * It cannot change while we are running, and every `acquireFileLock` — plus
40
+ * each retry attempt and each stale-lock reclaim guard — stamps the owner file
41
+ * with it. On Windows that probe is a `powershell.exe` spawn and a WMI query,
42
+ * so a process taking several locks pays it several times for one constant.
43
+ *
44
+ * A foreign pid is never cached: that process can exit and its pid can be
45
+ * reused, which is the very thing the stamp exists to detect. A failed probe
46
+ * is not cached either — one transient failure would otherwise leave the
47
+ * process unable to take a lock for its whole lifetime.
48
+ */
49
+ export function readProcessStartTimeCached(pid) {
50
+ if (pid !== process.pid)
51
+ return readProcessStartTime(pid);
52
+ return (ownStartTime ??= readProcessStartTime(pid));
53
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitnexus",
3
- "version": "1.6.12-rc.12",
3
+ "version": "1.6.12-rc.14",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",