Hyperlinkv0.8.0-beta.28

RcMap

RcMap.makeconsteffect/RcMap.ts:235
<K, A, E, R>(options: {
  readonly lookup: (key: K) => Effect.Effect<A, E, R>
  readonly idleTimeToLive?:
    | Duration.Input
    | ((key: K) => Duration.Input)
    | undefined
  readonly capacity?: undefined
}): Effect.Effect<RcMap<K, A, E>, never, Scope.Scope | R>
<K, A, E, R>(options: {
  readonly lookup: (key: K) => Effect.Effect<A, E, R>
  readonly idleTimeToLive?:
    | Duration.Input
    | ((key: K) => Duration.Input)
    | undefined
  readonly capacity: number
}): Effect.Effect<
  RcMap<K, A, E | Cause.ExceededCapacityError>,
  never,
  Scope.Scope | R
>

Creates an RcMap that can contain multiple reference counted resources that can be indexed by a key. The resources are lazily acquired on the first call to get and released when the last reference is released.

When to use

Use to create a scoped reference-counted map for resources that should be acquired once per key and shared while in use.

Details

Complex keys can extend Equal and Hash to allow lookups by value.

  • capacity: The maximum number of resources that can be held in the map.
  • idleTimeToLive: When the reference count reaches zero, the resource will be released after this duration.

Example (Creating a reference-counted map)

import { Effect, RcMap } from "effect"

Effect.gen(function*() {
  const map = yield* RcMap.make({
    lookup: (key: string) =>
      Effect.acquireRelease(
        Effect.succeed(`acquired ${key}`),
        () => Effect.log(`releasing ${key}`)
      )
  })

  // Get "foo" from the map twice, which will only acquire it once.
  // It will then be released once the scope closes.
  yield* RcMap.get(map, "foo").pipe(
    Effect.andThen(RcMap.get(map, "foo")),
    Effect.scoped
  )
})
Source effect/RcMap.ts:23549 lines
export const make: {
  <K, A, E, R>(options: {
    readonly lookup: (key: K) => Effect.Effect<A, E, R>
    readonly idleTimeToLive?: Duration.Input | ((key: K) => Duration.Input) | undefined
    readonly capacity?: undefined
  }): Effect.Effect<RcMap<K, A, E>, never, Scope.Scope | R>
  <K, A, E, R>(options: {
    readonly lookup: (key: K) => Effect.Effect<A, E, R>
    readonly idleTimeToLive?: Duration.Input | ((key: K) => Duration.Input) | undefined
    readonly capacity: number
  }): Effect.Effect<RcMap<K, A, E | Cause.ExceededCapacityError>, never, Scope.Scope | R>
} = <K, A, E, R>(options: {
  readonly lookup: (key: K) => Effect.Effect<A, E, R>
  readonly idleTimeToLive?: Duration.Input | ((key: K) => Duration.Input) | undefined
  readonly capacity?: number | undefined
}) =>
  Effect.withFiber<RcMap<K, A, E>, never, R | Scope.Scope>((fiber) => {
    const context = fiber.context as Context.Context<R | Scope.Scope>
    const scope = Context.get(context, Scope.Scope)
    const self = makeUnsafe<K, A, E>({
      lookup: options.lookup as any,
      context,
      scope,
      idleTimeToLive: typeof options.idleTimeToLive === "function"
        ? flow(options.idleTimeToLive, Duration.fromInputUnsafe)
        : constant(Duration.fromInputUnsafe(options.idleTimeToLive ?? Duration.zero)),
      capacity: Math.max(options.capacity ?? Number.POSITIVE_INFINITY, 0)
    })
    return Effect.as(
      Scope.addFinalizerExit(scope, () => {
        if (self.state._tag === "Closed") {
          return Effect.void
        }
        const map = self.state.map
        self.state = { _tag: "Closed" }
        return Effect.forEach(
          map,
          ([, entry]) => Effect.exit(Scope.close(entry.scope, Exit.void))
        ).pipe(
          Effect.tap(() =>
            Effect.sync(() => {
              MutableHashMap.clear(map)
            })
          )
        )
      }),
      self
    )
  })
Referenced by 1 symbols