"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.withRequestCaching = exports.withRequestCache = exports.withRequestBatching = exports.fromRequest = exports.currentCacheEnabled = exports.currentCache = exports.cacheRequest = void 0;
var Debug = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@effect/data/Debug"));
var _Duration = /*#__PURE__*/require("@effect/data/Duration");
var _Global = /*#__PURE__*/require("@effect/data/Global");
var BlockedRequests = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@effect/io/internal_effect_untraced/blockedRequests"));
var _cache = /*#__PURE__*/require("@effect/io/internal_effect_untraced/cache");
var _cause = /*#__PURE__*/require("@effect/io/internal_effect_untraced/cause");
var core = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@effect/io/internal_effect_untraced/core"));
var _fiberRuntime = /*#__PURE__*/require("@effect/io/internal_effect_untraced/fiberRuntime");
var _request = /*#__PURE__*/require("@effect/io/internal_effect_untraced/request");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/** @internal */
const currentCache = /*#__PURE__*/core.fiberRefUnsafeMake( /*#__PURE__*/(0, _cache.unsafeMakeWith)(65536, () => core.map(core.deferredMake(), handle => ({
  listeners: new _request.Listeners(),
  handle
})), () => (0, _Duration.seconds)(60)));
/** @internal */
exports.currentCache = currentCache;
const currentCacheEnabled = /*#__PURE__*/(0, _Global.globalValue)( /*#__PURE__*/Symbol.for("@effect/io/FiberRef/currentCacheEnabled"), () => core.fiberRefUnsafeMake(false));
/** @internal */
exports.currentCacheEnabled = currentCacheEnabled;
const fromRequest = /*#__PURE__*/Debug.methodWithTrace(trace => (request, dataSource) => {
  // @ts-expect-error
  return core.flatMap(core.isEffect(dataSource) ? dataSource : core.succeed(dataSource), ds => core.fiberIdWith(id => {
    const proxy = new Proxy(request, {});
    return core.fiberRefGetWith(currentCacheEnabled, cacheEnabled => {
      if (cacheEnabled) {
        return core.fiberRefGetWith(currentCache, cache => core.flatMap(cache.getEither(proxy), orNew => {
          switch (orNew._tag) {
            case "Left":
              {
                orNew.left.listeners.increment();
                return core.blocked(BlockedRequests.empty, core.flatMap(core.exit(core.deferredAwait(orNew.left.handle)), exit => {
                  if (exit._tag === "Failure" && (0, _cause.isInterruptedOnly)(exit.cause)) {
                    orNew.left.listeners.decrement();
                    return core.flatMap(cache.invalidateWhen(proxy, entry => entry.handle === orNew.left.handle), () => fromRequest(proxy, dataSource));
                  }
                  return (0, _fiberRuntime.ensuring)(core.deferredAwait(orNew.left.handle), core.sync(() => orNew.left.listeners.decrement()));
                }));
              }
            case "Right":
              {
                orNew.right.listeners.increment();
                return core.blocked(BlockedRequests.single(ds, BlockedRequests.makeEntry(proxy, orNew.right.handle, orNew.right.listeners, id, {
                  completed: false
                })), core.uninterruptibleMask(restore => core.flatMap(core.exit(restore(core.deferredAwait(orNew.right.handle))), exit => {
                  orNew.right.listeners.decrement();
                  return exit;
                })));
              }
          }
        }));
      }
      const listeners = new _request.Listeners();
      listeners.increment();
      return core.flatMap(core.deferredMake(), ref => core.blocked(BlockedRequests.single(ds, BlockedRequests.makeEntry(proxy, ref, listeners, id, {
        completed: false
      })), (0, _fiberRuntime.ensuring)(core.deferredAwait(ref), core.sync(() => listeners.decrement()))));
    });
  })).traced(trace);
});
/** @internal */
exports.fromRequest = fromRequest;
const cacheRequest = /*#__PURE__*/Debug.methodWithTrace(trace => (request, result) => {
  return core.fiberRefGetWith(currentCacheEnabled, cacheEnabled => {
    if (cacheEnabled) {
      return core.fiberRefGetWith(currentCache, cache => core.flatMap(cache.getEither(request), orNew => {
        switch (orNew._tag) {
          case "Left":
            {
              return core.unit();
            }
          case "Right":
            {
              return core.deferredComplete(orNew.right.handle, result);
            }
        }
      }));
    }
    return core.unit();
  }).traced(trace);
});
/** @internal */
exports.cacheRequest = cacheRequest;
const withRequestBatching = /*#__PURE__*/Debug.dualWithTrace(2, trace => (self, strategy) => core.fiberRefGetWith(_fiberRuntime.currentRequestBatchingEnabled, enabled => {
  switch (strategy) {
    case "off":
      return enabled ? core.fiberRefLocally(self, _fiberRuntime.currentRequestBatchingEnabled, false) : self;
    case "on":
      return enabled ? self : core.fiberRefLocally(self, _fiberRuntime.currentRequestBatchingEnabled, true);
  }
}).traced(trace));
/** @internal */
exports.withRequestBatching = withRequestBatching;
const withRequestCaching = /*#__PURE__*/Debug.dualWithTrace(2, trace => (self, strategy) => core.fiberRefGetWith(currentCacheEnabled, enabled => {
  switch (strategy) {
    case "off":
      return enabled ? core.fiberRefLocally(self, currentCacheEnabled, false) : self;
    case "on":
      return enabled ? self : core.fiberRefLocally(self, currentCacheEnabled, true);
  }
}).traced(trace));
/** @internal */
exports.withRequestCaching = withRequestCaching;
const withRequestCache = /*#__PURE__*/Debug.dualWithTrace(2,
// @ts-expect-error
trace => (self, cache) => core.fiberRefLocally(self, currentCache, cache).traced(trace));
exports.withRequestCache = withRequestCache;
//# sourceMappingURL=query.js.map