{"version":3,"sources":["../../src/leader/index.ts","../../src/leader/LeaderElection.ts"],"sourcesContent":["export { LeaderElection } from './LeaderElection.js'\nexport type { MeshLeaderHandle, MeshLeaderRecord, MeshLeaderRunOptions } from './types.js'\n","import type { LockManager } from '../locks/LockManager.js'\nimport type { MeshLockLease } from '../locks/types.js'\nimport type { MeshLeaderHandle, MeshLeaderRecord, MeshLeaderRunOptions } from './types.js'\n\nexport class LeaderElection {\n  public constructor(private readonly locks: LockManager, private readonly leaderId: string) {}\n\n  public async tryElect(group: string, options: MeshLeaderRunOptions = {}): Promise<MeshLeaderHandle | null> {\n    const lease = await this.locks.tryAcquire(this.key(group), {\n      ttlMs: options.ttlMs ?? 30_000,\n      waitMs: 0,\n      metadata: { ...(options.metadata ?? {}), group, leaderId: this.leaderId, kind: 'leader' }\n    })\n    return lease ? this.toHandle(group, lease) : null\n  }\n\n  public async elect(group: string, options: MeshLeaderRunOptions = {}): Promise<MeshLeaderHandle> {\n    const lease = await this.locks.acquire(this.key(group), {\n      ttlMs: options.ttlMs ?? 30_000,\n      waitMs: options.waitMs ?? 0,\n      metadata: { ...(options.metadata ?? {}), group, leaderId: this.leaderId, kind: 'leader' }\n    })\n    return this.toHandle(group, lease)\n  }\n\n  public async runWhenLeader<T>(group: string, fn: (signal: AbortSignal, leader: MeshLeaderHandle) => Promise<T> | T, options: MeshLeaderRunOptions = {}): Promise<T | null> {\n    const handle = await this.tryElect(group, options)\n    if (!handle) return null\n    const controller = new AbortController()\n    const ttlMs = options.ttlMs ?? 30_000\n    const every = options.renewEveryMs ?? Math.max(1_000, Math.floor(ttlMs / 2))\n    const timer = setInterval(() => { void handleRenew(handle, ttlMs, controller) }, every)\n    timer.unref?.()\n    try {\n      return await fn(controller.signal, handle)\n    } finally {\n      controller.abort()\n      clearInterval(timer)\n      await handle.release()\n    }\n  }\n\n  public async list(): Promise<readonly MeshLeaderRecord[]> {\n    const locks = await this.locks.list()\n    return locks\n      .filter(lock => lock.metadata?.kind === 'leader' && typeof lock.metadata.group === 'string')\n      .map(lock => ({\n        group: String(lock.metadata!.group),\n        leaderId: String(lock.metadata!.leaderId ?? lock.ownerId),\n        acquiredAt: lock.acquiredAt,\n        expiresAt: lock.expiresAt,\n        ...(lock.metadata ? { metadata: lock.metadata } : {})\n      }))\n      .sort((a, b) => a.group.localeCompare(b.group))\n  }\n\n  private toHandle(group: string, lease: MeshLockLease): MeshLeaderHandle & { renew(ttlMs?: number): Promise<boolean> } {\n    return {\n      group,\n      leaderId: this.leaderId,\n      acquiredAt: lease.acquiredAt,\n      expiresAt: lease.expiresAt,\n      release: () => lease.release(),\n      renew: (ttlMs?: number) => lease.renew(ttlMs)\n    }\n  }\n\n  private key(group: string): string {\n    return `leader:${group}`\n  }\n}\n\nasync function handleRenew(handle: MeshLeaderHandle & { renew?: (ttlMs?: number) => Promise<boolean> }, ttlMs: number, controller: AbortController): Promise<void> {\n  const renew = handle.renew\n  if (!renew) return\n  const ok = await renew(ttlMs)\n  if (!ok) controller.abort()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACIO,IAAM,iBAAN,MAAqB;AAAA,EACnB,YAA6B,OAAqC,UAAkB;AAAvD;AAAqC;AAAA,EAAmB;AAAA,EAAxD;AAAA,EAAqC;AAAA,EAEzE,MAAa,SAAS,OAAe,UAAgC,CAAC,GAAqC;AACzG,UAAM,QAAQ,MAAM,KAAK,MAAM,WAAW,KAAK,IAAI,KAAK,GAAG;AAAA,MACzD,OAAO,QAAQ,SAAS;AAAA,MACxB,QAAQ;AAAA,MACR,UAAU,EAAE,GAAI,QAAQ,YAAY,CAAC,GAAI,OAAO,UAAU,KAAK,UAAU,MAAM,SAAS;AAAA,IAC1F,CAAC;AACD,WAAO,QAAQ,KAAK,SAAS,OAAO,KAAK,IAAI;AAAA,EAC/C;AAAA,EAEA,MAAa,MAAM,OAAe,UAAgC,CAAC,GAA8B;AAC/F,UAAM,QAAQ,MAAM,KAAK,MAAM,QAAQ,KAAK,IAAI,KAAK,GAAG;AAAA,MACtD,OAAO,QAAQ,SAAS;AAAA,MACxB,QAAQ,QAAQ,UAAU;AAAA,MAC1B,UAAU,EAAE,GAAI,QAAQ,YAAY,CAAC,GAAI,OAAO,UAAU,KAAK,UAAU,MAAM,SAAS;AAAA,IAC1F,CAAC;AACD,WAAO,KAAK,SAAS,OAAO,KAAK;AAAA,EACnC;AAAA,EAEA,MAAa,cAAiB,OAAe,IAAuE,UAAgC,CAAC,GAAsB;AACzK,UAAM,SAAS,MAAM,KAAK,SAAS,OAAO,OAAO;AACjD,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,QAAQ,QAAQ,SAAS;AAC/B,UAAM,QAAQ,QAAQ,gBAAgB,KAAK,IAAI,KAAO,KAAK,MAAM,QAAQ,CAAC,CAAC;AAC3E,UAAM,QAAQ,YAAY,MAAM;AAAE,WAAK,YAAY,QAAQ,OAAO,UAAU;AAAA,IAAE,GAAG,KAAK;AACtF,UAAM,QAAQ;AACd,QAAI;AACF,aAAO,MAAM,GAAG,WAAW,QAAQ,MAAM;AAAA,IAC3C,UAAE;AACA,iBAAW,MAAM;AACjB,oBAAc,KAAK;AACnB,YAAM,OAAO,QAAQ;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAa,OAA6C;AACxD,UAAM,QAAQ,MAAM,KAAK,MAAM,KAAK;AACpC,WAAO,MACJ,OAAO,UAAQ,KAAK,UAAU,SAAS,YAAY,OAAO,KAAK,SAAS,UAAU,QAAQ,EAC1F,IAAI,WAAS;AAAA,MACZ,OAAO,OAAO,KAAK,SAAU,KAAK;AAAA,MAClC,UAAU,OAAO,KAAK,SAAU,YAAY,KAAK,OAAO;AAAA,MACxD,YAAY,KAAK;AAAA,MACjB,WAAW,KAAK;AAAA,MAChB,GAAI,KAAK,WAAW,EAAE,UAAU,KAAK,SAAS,IAAI,CAAC;AAAA,IACrD,EAAE,EACD,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,cAAc,EAAE,KAAK,CAAC;AAAA,EAClD;AAAA,EAEQ,SAAS,OAAe,OAAsF;AACpH,WAAO;AAAA,MACL;AAAA,MACA,UAAU,KAAK;AAAA,MACf,YAAY,MAAM;AAAA,MAClB,WAAW,MAAM;AAAA,MACjB,SAAS,MAAM,MAAM,QAAQ;AAAA,MAC7B,OAAO,CAAC,UAAmB,MAAM,MAAM,KAAK;AAAA,IAC9C;AAAA,EACF;AAAA,EAEQ,IAAI,OAAuB;AACjC,WAAO,UAAU,KAAK;AAAA,EACxB;AACF;AAEA,eAAe,YAAY,QAA6E,OAAe,YAA4C;AACjK,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAO;AACZ,QAAM,KAAK,MAAM,MAAM,KAAK;AAC5B,MAAI,CAAC,GAAI,YAAW,MAAM;AAC5B;","names":[]}