{"version":3,"file":"run-with-concurrency.mjs","names":[],"sources":["../../../../../../../ai/src/batch/run-with-concurrency.ts"],"sourcesContent":["/**\n * Run an async `worker` over every index `0..total-1` with at most\n * `limit` workers in flight at any moment, preserving nothing about\n * completion order (the worker is responsible for recording results\n * positionally). Resolves once every index has settled.\n *\n * A fixed pool of `limit` runners each pull the next unclaimed index\n * from a shared cursor — this keeps exactly `limit` items in flight\n * even when item durations vary wildly, unlike fixed-size chunking\n * which stalls a chunk on its slowest member.\n *\n * `limit` is clamped to `[1, total]`: a non-positive limit runs fully\n * serially, a limit larger than `total` simply starts every item.\n * `total === 0` resolves immediately.\n *\n * The worker must never reject — it owns its own try/catch and records\n * outcomes. A rejection here would abort sibling runners, which is not\n * the batch contract (one item's failure never cancels another's).\n */\nexport async function runWithConcurrency(\n  total: number,\n  limit: number,\n  worker: (index: number) => Promise<void>,\n): Promise<void> {\n  if (total <= 0) {\n    return;\n  }\n\n  const poolSize = Math.max(1, Math.min(limit, total));\n  let cursor = 0;\n\n  const runner = async (): Promise<void> => {\n    while (cursor < total) {\n      const index = cursor;\n      cursor += 1;\n      await worker(index);\n    }\n  };\n\n  const pool: Promise<void>[] = [];\n  for (let slot = 0; slot < poolSize; slot++) {\n    pool.push(runner());\n  }\n\n  await Promise.all(pool);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAmBA,eAAsB,mBACpB,OACA,OACA,QACe;CACf,IAAI,SAAS,GACX;CAGF,MAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,KAAK,CAAC;CACnD,IAAI,SAAS;CAEb,MAAM,SAAS,YAA2B;EACxC,OAAO,SAAS,OAAO;GACrB,MAAM,QAAQ;GACd,UAAU;GACV,MAAM,OAAO,KAAK;EACpB;CACF;CAEA,MAAM,OAAwB,CAAC;CAC/B,KAAK,IAAI,OAAO,GAAG,OAAO,UAAU,QAClC,KAAK,KAAK,OAAO,CAAC;CAGpB,MAAM,QAAQ,IAAI,IAAI;AACxB"}