Skip to content

[Duplicate Code] Extract shared lock lifecycle helper from identity managers #8893

Description

@github-actions

Duplicate Code Opportunity

Summary

  • Pattern: The lock acquisition loop plus stale-lock reclamation logic is repeated between the Cloud Hypervisor and NVX VMM identity managers.
  • Locations: src/cloud-hypervisor/vmm-identity.ts:372-430 and src/nvx/runtime-lifecycle.ts:414-455.
  • Impact: ~28 duplicated lines in a security-sensitive lifecycle path; a shared helper would reduce drift in lock ownership, timeout, and stale-lock recovery behavior.

Evidence

// src/cloud-hypervisor/vmm-identity.ts:372-430
const owner: LockOwner = {
  pid: this.dependencies.pid,
  startTime,
  nonce: randomBytes(16).toString('hex'),
};
const deadline = Date.now() + timeoutMs;
for (;;) {
  let acquired = false;
  try {
    await this.dependencies.mkdir(lockDirectory, { mode: 0o700 });
    acquired = true;
  } catch (error) {
    if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
  }
  if (acquired) {
    try {
      await this.dependencies.writeFile(
        path.join(lockDirectory, 'owner.json'),
        `${JSON.stringify(owner)}\n`,
        { flag: 'wx', mode: 0o600 },
      );
      return await operation();
    } finally {
      await this.removeOwnedLock(lockDirectory, owner);
    }
  }
  await this.reclaimStaleLock(lockDirectory);
  if (Date.now() >= deadline) {
    throw new Error('Timed out waiting for the Cloud Hypervisor VMM identity lock');
  }
  await this.dependencies.sleep(ACCOUNT_LOCK_RETRY_MS);
}
// src/nvx/runtime-lifecycle.ts:414-455
const owner = {
  pid: this.dependencies.pid,
  startTime,
  nonce: randomBytes(16).toString('hex'),
};
const deadline = Date.now() + timeoutMs;
for (;;) {
  let acquired = false;
  try {
    await this.dependencies.mkdir(lockDirectory, { mode: 0o700 });
    acquired = true;
  } catch (error) {
    if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
  }
  if (acquired) {
    try {
      await this.dependencies.writeFile(
        path.join(lockDirectory, 'owner.json'),
        `${JSON.stringify(owner)}\n`,
        { flag: 'wx', mode: '600' },
      );
      return await operation();
    } finally {
      await this.removeOwnedLock(lockDirectory, owner);
    }
  }
  await this.reclaimStaleLock(lockDirectory);
  if (Date.now() >= deadline) throw new Error('Timed out waiting for the NVX lifecycle lock');
  await this.dependencies.sleep(LOCK_RETRY_MS);
}

Suggested Refactoring

  • Extract a shared withLock() / reclaimStaleLock() helper into a common lifecycle utility module.
  • Parameterize the file-system policy differences (LOCK_RETRY_MS vs ACCOUNT_LOCK_RETRY_MS, stale-lock thresholds, reaper handling, and error strings) instead of reimplementing the loop in each manager.
  • Keep manager-specific cleanup (removeOwnedLock, tryClaimReaper) as injected callbacks so the core acquisition flow stays identical.

Affected Files

  • src/cloud-hypervisor/vmm-identity.ts — lines 372-430
  • src/nvx/runtime-lifecycle.ts — lines 414-455

Effort Estimate

Medium


Detected by Duplicate Code Detector workflow. Run date: 2026-09-22

Generated by Duplicate Code Detector · copilot · gpt50mini · 5.91 AIC · ⊞ 21K ·

  • expires on Oct 22, 2026, 9:44 PM UTC

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions