Skip to main content Link Search Menu Expand Document (external link)

Cache overview

This module implements a cache with a fixed capacity and time-to-live. The contents of the cache is populated by a lookup function which may be recursive. The cache capacity may temporarily be exceeded if the lookup function is recursive (because the cache is also used to determine circularity). Keys are compared using Equal.equals.


Table of contents


Constructors

make

Creates a new cache. The lookup function is used to populate the cache. If the capacity is undefined, the cache is unbounded. If the lifespan is undefined, the values never expire. Keys are compared using Equal.equals.

Signature

export declare const make: <A, B>({
  lookUp,
  capacity,
  lifeSpan
}: {
  readonly lookUp: LookUp<A, B>
  readonly capacity?: number
  readonly lifeSpan?: number
}) => Type<A, B>

Example

import { MCache, MTypes } from "@parischap/effect-lib"
import { Record, Tuple, pipe } from "effect"

export const nonRecursiveCache = MCache.make({
  lookUp: ({ key }: { readonly key: number }) => Tuple.make(key * 2, true)
})

interface RecursiveStructure {
  // eslint-disable-next-line functional/prefer-readonly-type
  [key: string]: string | RecursiveStructure
}

export const recursiveCache = MCache.make<RecursiveStructure, string>({
  lookUp: ({ key, memoized, isCircular }) =>
    isCircular
      ? Tuple.make(`Circular`, false)
      : Tuple.make(
          pipe(
            key,
            Record.reduce("", (acc, value) => (MTypes.isString(value) ? acc + value : acc + memoized(value)))
          ),
          true
        ),
  capacity: 2
})

Destructors

get

Gets a value from the cache. If the value is not in the cache (value comparison is based on Equal.equals), the lookup function is called to populate the cache. If it is in the cache but is too old,the lookup function is called to refresh it.

Signature

export declare const get: <A>(a: A) => <B>(self: Type<A, B>) => B

Example

import { MCache } from "@parischap/effect-lib"
import { Tuple } from "effect"

const testCache = MCache.make({
  lookUp: ({ key }: { readonly key: number }) => Tuple.make(key * 2, true)
})

assert.deepStrictEqual(MCache.get(3)(testCache), 6)

keysInStore

Returns an array of the keys whose value is currently stored in the cache

Signature

export declare const keysInStore: <A, B>(self: Type<A, B>) => Array<A>

toGetter

Returns a function that gets a value from the self

Signature

export declare const toGetter: <A, B>(self: Type<A, B>) => MTypes.OneArgFunction<A, B>

Guards

has

Type guard

Signature

export declare const has: (u: unknown) => u is Type<unknown, unknown>

Models

LookUp (type alias)

Type that represents the lookup function. In addition to the key, the lookup function receives a memoized version of itself if it needs to perform recursion. It also receives a flag indicating whether circularity was detected. In that case, the memoized version of the function is not passed as recursion should be stopped to avoid an infinite loop. The output of the function must contain the result of the lookup and a boolean indicating whether the result should be stored in the cache. Note that when isCircular is true, the result is not stored in the cache even if the result of the function indicates it should.

Signature

export type LookUp<A, B> = ({
  key,
  memoized,
  isCircular
}:
  | { readonly key: A; readonly memoized: undefined; readonly isCircular: true }
  | { readonly key: A; readonly memoized: (a: A) => B; readonly isCircular: false }) => MTypes.Pair<B, boolean>

Type (interface)

Type that represents a Cache

Signature

export interface Type<in out A, in out B> extends Inspectable.Inspectable, Pipeable.Pipeable {
  /**
   * The key/value cache. A None value means the value is currently under calculation. A circular
   * flag will be sent if the value needs to be retreived while it is being calculated.
   */
  readonly store: MutableHashMap.MutableHashMap<A, Option.Option<ValueContainer.Type<B>>>
  /**
   * A queue used to track the order in which keys were inserted so as to remove the oldest keys
   * first in case the cache has bounded capacity
   */
  readonly keyOrder: MutableQueue.MutableQueue<A>
  /** The lookup function used to populate the cache */
  readonly lookUp: LookUp<A, B>
  /** The capicity of the cache. If undefined, the cache is unbounded */
  readonly capacity: number | undefined
  /** The lifespan of the values in the cache. If undefined, the values never expire */
  readonly lifeSpan: number | undefined
  /** @internal */
  readonly [_TypeId]: {
    readonly _A: Types.Invariant<A>
    readonly _B: Types.Invariant<B>
  }
}

moduleTag

Module tag

Signature

export declare const moduleTag: "@parischap/effect-lib/Cache/"