@rotorsoft/act-http 1.10.13 → 1.10.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19695,6 +19695,57 @@ function date4(params) {
19695
19695
  return _coercedDate(ZodDate, params);
19696
19696
  }
19697
19697
 
19698
+ // src/api/in-flight.ts
19699
+ function track_in_flight(store) {
19700
+ const pending = /* @__PURE__ */ new Map();
19701
+ const up = (key) => pending.set(key, (pending.get(key) ?? 0) + 1);
19702
+ const down = (key) => {
19703
+ const left = (pending.get(key) ?? 0) - 1;
19704
+ if (left > 0) pending.set(key, left);
19705
+ else pending.delete(key);
19706
+ };
19707
+ const settle2 = (key, won) => {
19708
+ if (!won) down(key);
19709
+ return won;
19710
+ };
19711
+ return {
19712
+ in_flight: (key) => pending.has(key),
19713
+ store: {
19714
+ claim(key, now) {
19715
+ up(key);
19716
+ let won;
19717
+ try {
19718
+ won = store.claim(key, now);
19719
+ } catch (err) {
19720
+ down(key);
19721
+ throw err;
19722
+ }
19723
+ return typeof won === "boolean" ? settle2(key, won) : won.then(
19724
+ (w) => settle2(key, w),
19725
+ (err) => {
19726
+ down(key);
19727
+ throw err;
19728
+ }
19729
+ );
19730
+ },
19731
+ async commit(key, now) {
19732
+ try {
19733
+ await store.commit(key, now);
19734
+ } finally {
19735
+ down(key);
19736
+ }
19737
+ },
19738
+ async release(key) {
19739
+ try {
19740
+ await store.release(key);
19741
+ } finally {
19742
+ down(key);
19743
+ }
19744
+ }
19745
+ }
19746
+ };
19747
+ }
19748
+
19698
19749
  // src/api/errors.ts
19699
19750
  var import_act = require("@rotorsoft/act");
19700
19751
  var ERROR_MAP = {
@@ -19902,6 +19953,7 @@ function status_to_trpc_code(status) {
19902
19953
  }
19903
19954
  function trpc(app, options) {
19904
19955
  const t = import_server.initTRPC.context().create();
19956
+ const tracker = options.idempotency ? track_in_flight(options.idempotency.store) : void 0;
19905
19957
  const resolve_actor = async (host_ctx) => {
19906
19958
  try {
19907
19959
  return await options.actor(host_ctx);
@@ -19937,10 +19989,16 @@ function trpc(app, options) {
19937
19989
  });
19938
19990
  }
19939
19991
  const outcome = await withIdempotency(
19940
- options.idempotency.store,
19992
+ tracker.store,
19941
19993
  key,
19942
19994
  () => app.do(action_name, target, input2)
19943
19995
  );
19996
+ if (outcome.deduped && tracker.in_flight(key)) {
19997
+ throw new import_server.TRPCError({
19998
+ code: "SERVICE_UNAVAILABLE",
19999
+ message: "Idempotency-Key in flight; the original request has not finished, retry later"
20000
+ });
20001
+ }
19944
20002
  if (outcome.deduped) {
19945
20003
  throw new import_server.TRPCError({
19946
20004
  code: "CONFLICT",