{"version":3,"file":"formGroupsCache-Bbz-28ws.cjs","names":[],"sources":["../src/services/formGroupsCache.js"],"sourcesContent":["// formGroupsCache — one network request per distinct form-groups query.\n//\n// WHY\n// A single page routinely asks for the SAME form-groups payload several times\n// over, because the parts that need it are independent of each other and none\n// of them can know the others exist: on Quick Submit the job header card, the\n// form's cross-module prefill and a job-source lookup each fetch the same job,\n// and the submission config is fetched once unscoped and again client-scoped.\n// Those payloads are large (60 kB for a submission config), so the duplicates\n// are the expensive kind — a measured 245-request, ~4.8 s load with several\n// identical 60 kB and 15 kB responses in it.\n//\n// The honest fix is not to make each caller aware of the others — that couples\n// components that have no business knowing about each other, and breaks the\n// moment a new one is added. It is to make the REQUEST idempotent: identical\n// queries fired close together share one response.\n//\n// TWO MECHANISMS, deliberately:\n//\n//   • in-flight coalescing — a query that is already running is joined rather\n//     than reissued. Always safe: the answer cannot be staler than the request\n//     that is still in the air.\n//   • a SHORT time-to-live — covers the common case where the duplicates are\n//     sequential rather than overlapping (a child mounts after its parent's\n//     fetch has already resolved). This is the part that can serve stale data,\n//     so it is kept to a few seconds and any write invalidates the whole cache.\n//\n// Errors are never cached: a failed fetch removes its entry so the next caller\n// retries for real instead of inheriting the failure.\n//\n// Nothing here knows a module or a field. The cache key is the request URL, so\n// scopes that differ in any way (id, clientId, view, group, action) are\n// different entries and can never be served each other's data.\n\n// Long enough to cover one page's mount burst, short enough that no realistic\n// user action fits inside it. Writes invalidate regardless — see below.\nconst DEFAULT_TTL_MS = 4000;\n\nconst entries = new Map(); // url -> { at, promise }\n\nlet ttlMs = DEFAULT_TTL_MS;\n\n/** Test/host hook: change the window, or set 0 to keep only in-flight coalescing. */\nexport function setFormGroupsCacheTtl(ms) {\n  ttlMs = Math.max(0, Number(ms) || 0);\n}\n\n/**\n * Drop everything. Called after any module write: a save is exactly the moment\n * a cached payload stops describing the record, and a stale read here would\n * show the user their own change missing.\n */\nexport function invalidateFormGroupsCache() {\n  entries.clear();\n}\n\n/**\n * fetchFormGroupsCached — run `loader()` for `url`, or join/replay a recent\n * identical run.\n *\n * `loader` returns the RAW payload, so every caller shares one request no\n * matter which shape it goes on to read out of it (the groups array, or the\n * whole envelope with recordMeta).\n */\nexport function fetchFormGroupsCached(url, loader) {\n  const now = Date.now();\n  const hit = entries.get(url);\n  // A pending entry is always joinable; a settled one only within the window.\n  if (hit && (hit.pending || now - hit.at < ttlMs)) return hit.promise;\n\n  const entry = { at: now, pending: true };\n  entry.promise = Promise.resolve()\n    .then(loader)\n    .then((value) => {\n      entry.pending = false;\n      // Stamp on COMPLETION, not on start: a slow request must not begin life\n      // already half-expired, or a burst behind it would reissue immediately.\n      entry.at = Date.now();\n      return value;\n    })\n    .catch((err) => {\n      // Never cache a failure — the next caller must get a real attempt.\n      if (entries.get(url) === entry) entries.delete(url);\n      throw err;\n    });\n  entries.set(url, entry);\n  return entry.promise;\n}\n\nexport default { fetchFormGroupsCached, invalidateFormGroupsCache, setFormGroupsCacheTtl };\n"],"mappings":"kHAoCM,EAAiB,IAEjB,EAAU,IAAI,IAEhB,EAAQ,EAYZ,SAAgB,GAA4B,CAC1C,EAAQ,MAAM,CAChB,CAUA,SAAgB,EAAsB,EAAK,EAAQ,CACjD,IAAM,EAAM,KAAK,IAAI,EACf,EAAM,EAAQ,IAAI,CAAG,EAE3B,GAAI,IAAQ,EAAI,SAAW,EAAM,EAAI,GAAK,GAAQ,OAAO,EAAI,QAE7D,IAAM,EAAQ,CAAE,GAAI,EAAK,QAAS,EAAK,EAgBvC,MAfA,GAAM,QAAU,QAAQ,QAAQ,CAAC,CAC9B,KAAK,CAAM,CAAC,CACZ,KAAM,IACL,EAAM,QAAU,GAGhB,EAAM,GAAK,KAAK,IAAI,EACb,EACR,CAAC,CACD,MAAO,GAAQ,CAGd,MADI,EAAQ,IAAI,CAAG,IAAM,GAAO,EAAQ,OAAO,CAAG,EAC5C,CACR,CAAC,EACH,EAAQ,IAAI,EAAK,CAAK,EACf,EAAM,OACf"}