Hyperlinkv0.8.0-beta.28

Cache

Cache.refreshconsteffect/Cache.ts:1071
<Key, A>(key: Key): <E, R>(
  self: Cache<Key, A, E, R>
) => Effect.Effect<A, E, R>
<Key, A, E, R>(self: Cache<Key, A, E, R>, key: Key): Effect.Effect<
  A,
  E,
  R
>

Forces a refresh of the value associated with the specified key in the cache.

Details

It will always invoke the lookup function to construct a new value, overwriting any existing value for that key.

Example (Refreshing cached values)

import { Cache, Effect } from "effect"

// Force refresh of existing cached values
const program = Effect.gen(function*() {
  let counter = 0
  const cache = yield* Cache.make({
    capacity: 10,
    lookup: (key: string) => Effect.sync(() => `${key}-${++counter}`)
  })

  // Initial cache population
  const value1 = yield* Cache.get(cache, "user")
  console.log(value1) // "user-1"

  // Get from cache (no lookup)
  const value2 = yield* Cache.get(cache, "user")
  console.log(value2) // "user-1" (same value)

  // Force refresh - always calls lookup
  const refreshed = yield* Cache.refresh(cache, "user")
  console.log(refreshed) // "user-2" (new value)

  // Subsequent gets return refreshed value
  const value3 = yield* Cache.get(cache, "user")
  console.log(value3) // "user-2"
})

Example (Resetting TTL on refresh)

import { Cache, Effect } from "effect"
import { TestClock } from "effect/testing"

// Refresh resets TTL (Time To Live)
const program = Effect.gen(function*() {
  const cache = yield* Cache.make({
    capacity: 10,
    lookup: (key: string) => Effect.succeed(key.length),
    timeToLive: "1 hour"
  })

  yield* Cache.get(cache, "test")
  yield* TestClock.adjust("45 minutes")

  // Entry would normally expire in 15 minutes
  console.log(yield* Cache.has(cache, "test")) // true

  // Refresh resets the TTL to full 1 hour
  yield* Cache.refresh(cache, "test")
  yield* TestClock.adjust("30 minutes")

  // Still valid because TTL was reset
  console.log(yield* Cache.has(cache, "test")) // true
})

Example (Refreshing missing keys)

import { Cache, Effect } from "effect"

// Refresh non-existent keys
const program = Effect.gen(function*() {
  const cache = yield* Cache.make({
    capacity: 10,
    lookup: (key: string) => Effect.succeed(`value-for-${key}`)
  })

  // Refresh non-existent key creates new entry
  const result = yield* Cache.refresh(cache, "newKey")
  console.log(result) // "value-for-newKey"

  // Verify it's now cached
  console.log(yield* Cache.has(cache, "newKey")) // true
})
combinators
Source effect/Cache.ts:107134 lines
export const refresh: {
  <Key, A>(key: Key): <E, R>(self: Cache<Key, A, E, R>) => Effect.Effect<A, E, R>
  <Key, A, E, R>(self: Cache<Key, A, E, R>, key: Key): Effect.Effect<A, E, R>
} = dual(
  2,
  <Key, A, E, R>(self: Cache<Key, A, E, R>, key: Key): Effect.Effect<A, E, R> =>
    core.withFiber((fiber) => {
      const deferred = Deferred.makeUnsafe<A, E>()
      const entry: Entry<A, E> = {
        expiresAt: undefined,
        deferred
      }
      const existing = getImpl(self, key, fiber, false) !== undefined
      if (!existing) {
        MutableHashMap.set(self.map, key, entry)
        checkCapacity(self)
      }
      return effect.onExit(self.lookup(key), (exit) => {
        Deferred.doneUnsafe(deferred, exit)
        const ttl = self.timeToLive(exit, key)
        if (Duration.isZero(ttl)) {
          MutableHashMap.remove(self.map, key)
          return effect.void
        }
        entry.expiresAt = Duration.isFinite(ttl)
          ? fiber.getRef(effect.ClockRef).currentTimeMillisUnsafe() + Duration.toMillis(ttl)
          : undefined
        if (existing) {
          MutableHashMap.set(self.map, key, entry)
        }
        return effect.void
      })
    })
)