import * as Context from "../../Context.js";
import * as Duration from "../../Duration.js";
import * as Effect from "../../Effect.js";
import { identity } from "../../Function.js";
import * as RcRef from "../../RcRef.js";
import * as Scope from "../../Scope.js";
import * as Entity from "./Entity.js";
import * as K8sHttpClient from "./K8sHttpClient.js";
/**
 * Type identifier used to brand `EntityResource` values.
 *
 * @category type IDs
 * @since 4.0.0
 */
export const TypeId = "~effect/cluster/EntityResource";
/**
 * Context service for a Scope that is only closed when the resource is explicitly closed.
 *
 * **Gotchas**
 *
 * It is not closed during restarts, due to shard movement or node shutdowns.
 *
 * @category resource management
 * @since 4.0.0
 */
export class CloseScope extends /*#__PURE__*/Context.Service()("effect/cluster/EntityResource/CloseScope") {}
/**
 * Creates an `EntityResource` that can be acquired inside a cluster entity.
 *
 * **Details**
 *
 * The resource will only be fully released when the idle time to live is
 * reached, or when the `close` effect is called.
 *
 * **Gotchas**
 *
 * By default, the `idleTimeToLive` is infinite, meaning the resource will only
 * be released when `close` is called.
 *
 * @category constructors
 * @since 4.0.0
 */
export const make = /*#__PURE__*/Effect.fnUntraced(function* (options) {
  let shuttingDown = false;
  const ref = yield* RcRef.make({
    acquire: Effect.gen(function* () {
      yield* Entity.keepAlive(true);
      const closeable = yield* Scope.make();
      yield* Effect.addFinalizer(Effect.fnUntraced(function* (exit) {
        if (shuttingDown) return;
        yield* Scope.close(closeable, exit);
        yield* Entity.keepAlive(false);
      }));
      return yield* options.acquire.pipe(Effect.provideService(CloseScope, closeable));
    }),
    idleTimeToLive: options.idleTimeToLive ?? Duration.infinity
  });
  yield* Effect.addFinalizer(() => {
    shuttingDown = true;
    return Effect.void;
  });
  if (options.acquireEagerly) {
    // Initialize the resource
    yield* Effect.scoped(RcRef.get(ref));
  }
  return identity({
    [TypeId]: TypeId,
    get: RcRef.get(ref),
    close: RcRef.invalidate(ref)
  });
});
/**
 * Creates an `EntityResource` backed by a Kubernetes Pod.
 *
 * **Details**
 *
 * The pod is created and waited on through `K8sHttpClient`, and is kept alive
 * until the resource is closed or its idle time to live expires.
 *
 * @category Kubernetes
 * @since 4.0.0
 */
export const makeK8sPod = /*#__PURE__*/Effect.fnUntraced(function* (spec, options) {
  const createPod = yield* K8sHttpClient.makeCreatePod;
  return yield* make({
    ...options,
    acquire: Effect.gen(function* () {
      const scope = yield* CloseScope;
      return yield* createPod(spec).pipe(Scope.provide(scope));
    })
  });
});
//# sourceMappingURL=EntityResource.js.map