// src/concurrency.ts
var Mutex = class {
  locked = false;
  waiters = [];
  async acquire() {
    if (!this.locked) {
      this.locked = true;
      return () => this.release();
    }
    return new Promise((resolve) => {
      this.waiters.push(() => {
        resolve(() => this.release());
      });
    });
  }
  release() {
    const next = this.waiters.shift();
    if (next) {
      next();
    } else {
      this.locked = false;
    }
  }
  async runExclusive(fn) {
    const release = await this.acquire();
    try {
      return await fn();
    } finally {
      release();
    }
  }
  /** True iff someone holds the lock right now. Diagnostics only. */
  get isLocked() {
    return this.locked;
  }
  /** Pending waiter count. Diagnostics only. */
  get pending() {
    return this.waiters.length;
  }
};

// src/locked-jsonl-appender.ts
import { appendFileSync, existsSync, mkdirSync } from "fs";
import { dirname } from "path";
var mutexes = /* @__PURE__ */ new Map();
function getMutex(path) {
  let m = mutexes.get(path);
  if (!m) {
    m = new Mutex();
    mutexes.set(path, m);
  }
  return m;
}
var LockedJsonlAppender = class {
  constructor(path) {
    this.path = path;
    this.mutex = getMutex(path);
    if (!existsSync(dirname(path))) {
      mkdirSync(dirname(path), { recursive: true });
    }
  }
  path;
  mutex;
  async append(entry) {
    const line = `${JSON.stringify(entry)}
`;
    await this.mutex.runExclusive(() => {
      appendFileSync(this.path, line);
    });
  }
};
function resetLockedAppendersForTesting() {
  mutexes.clear();
}

export {
  Mutex,
  LockedJsonlAppender,
  resetLockedAppendersForTesting
};
//# sourceMappingURL=chunk-DJWX3GVS.js.map