Skip to content

Instantly share code, notes, and snippets.

@tim-smart
Created February 9, 2024 00:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tim-smart/fd87d99ab23e242b5c1ebf8f7a58ba1a to your computer and use it in GitHub Desktop.
Save tim-smart/fd87d99ab23e242b5c1ebf8f7a58ba1a to your computer and use it in GitHub Desktop.
import type { Duration, Scope } from "effect"
import { Effect, SynchronizedRef } from "effect"
export const make = (limit: number, window: Duration.DurationInput): Effect.Effect<
<A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>,
never,
Scope.Scope
> =>
Effect.gen(function*(_) {
const scope = yield* _(Effect.scope)
const semaphore = yield* _(Effect.makeSemaphore(limit))
const ref = yield* _(SynchronizedRef.make(false))
const reset = SynchronizedRef.updateEffect(ref, (running) =>
running ? Effect.succeed(true) : Effect.sleep(window).pipe(
Effect.zipRight(SynchronizedRef.set(ref, false)),
Effect.zipRight(semaphore.releaseAll),
Effect.forkIn(scope),
Effect.interruptible,
Effect.as(true)
))
const take = Effect.zipRight(semaphore.take(1), reset)
return (effect) =>
Effect.zipRight(take, effect)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment