Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSDocs: add examples to caching functions #3008

Merged
merged 1 commit into from
Jun 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 144 additions & 20 deletions packages/effect/src/Effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,38 @@ export const isEffect: (u: unknown) => u is Effect<unknown, unknown, unknown> =
// -------------------------------------------------------------------------------------

/**
* Returns an effect that, if evaluated, will return the cached result of this
* effect. Cached results will expire after `timeToLive` duration.
* Returns an effect that caches its result for a specified duration, known as
* the `timeToLive`. When the cache expires after the duration, the effect will be
* recomputed upon next evaluation.
*
* @example
* import { Effect, Console } from "effect"
*
* let i = 1
* const expensiveTask = Effect.promise<string>(() => {
* console.log("expensive task...")
* return new Promise((resolve) => {
* setTimeout(() => {
* resolve(`result ${i++}`)
* }, 100)
* })
* })
*
* const program = Effect.gen(function* () {
* const cached = yield* Effect.cachedWithTTL(expensiveTask, "150 millis")
* yield* cached.pipe(Effect.andThen(Console.log))
* yield* cached.pipe(Effect.andThen(Console.log))
* yield* Effect.sleep("100 millis")
* yield* cached.pipe(Effect.andThen(Console.log))
* })
*
* // Effect.runFork(program)
* // Output:
* // expensive task...
* // result 1
* // result 1
* // expensive task...
* // result 2
*
* @since 2.0.0
* @category caching
Expand All @@ -278,10 +308,41 @@ export const cachedWithTTL: {
} = circular.cached

/**
* Returns an effect that, if evaluated, will return the cached result of this
* effect. Cached results will expire after `timeToLive` duration. In
* addition, returns an effect that can be used to invalidate the current
* cached value before the `timeToLive` duration expires.
* Similar to {@link cachedWithTTL}, this function caches an effect's result for a
* specified duration. It also includes an additional effect for manually
* invalidating the cached value before it naturally expires.
*
* @example
* import { Effect, Console } from "effect"
*
* let i = 1
* const expensiveTask = Effect.promise<string>(() => {
* console.log("expensive task...")
* return new Promise((resolve) => {
* setTimeout(() => {
* resolve(`result ${i++}`)
* }, 100)
* })
* })
*
* const program = Effect.gen(function* () {
* const [cached, invalidate] = yield* Effect.cachedInvalidateWithTTL(
* expensiveTask,
* "1 hour"
* )
* yield* cached.pipe(Effect.andThen(Console.log))
* yield* cached.pipe(Effect.andThen(Console.log))
* yield* invalidate
* yield* cached.pipe(Effect.andThen(Console.log))
* })
*
* // Effect.runFork(program)
* // Output:
* // expensive task...
* // result 1
* // result 1
* // expensive task...
* // result 2
*
* @since 2.0.0
* @category caching
Expand All @@ -297,16 +358,78 @@ export const cachedInvalidateWithTTL: {
} = circular.cachedInvalidateWithTTL

/**
* Returns an effect that, if evaluated, will return the lazily computed
* result of this effect.
* Returns an effect that computes a result lazily and caches it. Subsequent
* evaluations of this effect will return the cached result without re-executing
* the logic.
*
* @example
* import { Effect, Console } from "effect"
*
* let i = 1
* const expensiveTask = Effect.promise<string>(() => {
* console.log("expensive task...")
* return new Promise((resolve) => {
* setTimeout(() => {
* resolve(`result ${i++}`)
* }, 100)
* })
* })
*
* const program = Effect.gen(function* () {
* console.log("non-cached version:")
* yield* expensiveTask.pipe(Effect.andThen(Console.log))
* yield* expensiveTask.pipe(Effect.andThen(Console.log))
* console.log("cached version:")
* const cached = yield* Effect.cached(expensiveTask)
* yield* cached.pipe(Effect.andThen(Console.log))
* yield* cached.pipe(Effect.andThen(Console.log))
* })
*
* // Effect.runFork(program)
* // Output:
* // non-cached version:
* // expensive task...
* // result 1
* // expensive task...
* // result 2
* // cached version:
* // expensive task...
* // result 3
* // result 3
*
* @since 2.0.0
* @category caching
*/
export const cached: <A, E, R>(self: Effect<A, E, R>) => Effect<Effect<A, E, R>> = effect.memoize

/**
* Returns a memoized version of the specified effectual function.
* Returns a memoized version of a function with effects. Memoization ensures
* that results are stored and reused for the same inputs, reducing the need to
* recompute them.
*
* @example
* import { Effect, Random } from "effect"
*
* const program = Effect.gen(function* () {
* const randomNumber = (n: number) => Random.nextIntBetween(1, n)
* console.log("non-memoized version:")
* console.log(yield* randomNumber(10))
* console.log(yield* randomNumber(10))
*
* console.log("memoized version:")
* const memoized = yield* Effect.cachedFunction(randomNumber)
* console.log(yield* memoized(10))
* console.log(yield* memoized(10))
* })
*
* // Effect.runFork(program)
* // Example Output:
* // non-memoized version:
* // 2
* // 8
* // memoized version:
* // 5
* // 5
*
* @since 2.0.0
* @category caching
Expand All @@ -317,24 +440,25 @@ export const cachedFunction: <A, B, E, R>(
) => Effect<(a: A) => Effect<B, E, R>> = circular.cachedFunction

/**
* Returns an effect that will be executed at most once, even if it is
* evaluated multiple times.
* Returns an effect that executes only once, regardless of how many times it's
* called.
*
* @example
* import { Effect, Console } from "effect"
*
* const program = Effect.gen(function* (_) {
* const twice = Console.log("twice")
* yield* _(twice, Effect.repeatN(1))
* const once = yield* _(Console.log("once"), Effect.once)
* yield* _(once, Effect.repeatN(1))
* const program = Effect.gen(function* () {
* const task1 = Console.log("task1")
* yield* Effect.repeatN(task1, 2)
* const task2 = yield* Effect.once(Console.log("task2"))
* yield* Effect.repeatN(task2, 2)
* })
*
* Effect.runFork(program)
* // Effect.runFork(program)
* // Output:
* // twice
* // twice
* // once
* // task1
* // task1
* // task1
* // task2
*
* @since 2.0.0
* @category caching
Expand Down