effect 2.3.1 → 2.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/cjs/Effect.js.map +1 -1
  2. package/dist/cjs/Either.js +4 -1
  3. package/dist/cjs/Either.js.map +1 -1
  4. package/dist/cjs/Option.js +4 -1
  5. package/dist/cjs/Option.js.map +1 -1
  6. package/dist/cjs/RateLimiter.js +67 -1
  7. package/dist/cjs/RateLimiter.js.map +1 -1
  8. package/dist/cjs/Scheduler.js +3 -4
  9. package/dist/cjs/Scheduler.js.map +1 -1
  10. package/dist/cjs/internal/clock.js +2 -3
  11. package/dist/cjs/internal/clock.js.map +1 -1
  12. package/dist/cjs/internal/effect/circular.js +10 -8
  13. package/dist/cjs/internal/effect/circular.js.map +1 -1
  14. package/dist/cjs/internal/fiberRuntime.js +12 -2
  15. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  16. package/dist/cjs/internal/rateLimiter.js +39 -8
  17. package/dist/cjs/internal/rateLimiter.js.map +1 -1
  18. package/dist/cjs/internal/version.js +1 -1
  19. package/dist/dts/Effect.d.ts +7 -3
  20. package/dist/dts/Effect.d.ts.map +1 -1
  21. package/dist/dts/Either.d.ts +4 -0
  22. package/dist/dts/Either.d.ts.map +1 -1
  23. package/dist/dts/FiberSet.d.ts +4 -4
  24. package/dist/dts/FiberSet.d.ts.map +1 -1
  25. package/dist/dts/Option.d.ts +4 -0
  26. package/dist/dts/Option.d.ts.map +1 -1
  27. package/dist/dts/RateLimiter.d.ts +109 -10
  28. package/dist/dts/RateLimiter.d.ts.map +1 -1
  29. package/dist/dts/Scheduler.d.ts.map +1 -1
  30. package/dist/dts/index.d.ts +1 -5
  31. package/dist/dts/index.d.ts.map +1 -1
  32. package/dist/dts/internal/version.d.ts +1 -1
  33. package/dist/esm/Effect.js.map +1 -1
  34. package/dist/esm/Either.js +4 -1
  35. package/dist/esm/Either.js.map +1 -1
  36. package/dist/esm/Option.js +4 -1
  37. package/dist/esm/Option.js.map +1 -1
  38. package/dist/esm/RateLimiter.js +66 -0
  39. package/dist/esm/RateLimiter.js.map +1 -1
  40. package/dist/esm/Scheduler.js +3 -4
  41. package/dist/esm/Scheduler.js.map +1 -1
  42. package/dist/esm/index.js +1 -5
  43. package/dist/esm/index.js.map +1 -1
  44. package/dist/esm/internal/clock.js +2 -3
  45. package/dist/esm/internal/clock.js.map +1 -1
  46. package/dist/esm/internal/effect/circular.js +10 -8
  47. package/dist/esm/internal/effect/circular.js.map +1 -1
  48. package/dist/esm/internal/fiberRuntime.js +12 -2
  49. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  50. package/dist/esm/internal/rateLimiter.js +36 -6
  51. package/dist/esm/internal/rateLimiter.js.map +1 -1
  52. package/dist/esm/internal/version.js +1 -1
  53. package/package.json +1 -1
  54. package/src/Effect.ts +7 -3
  55. package/src/Either.ts +8 -1
  56. package/src/FiberSet.ts +4 -4
  57. package/src/Option.ts +8 -1
  58. package/src/RateLimiter.ts +111 -14
  59. package/src/Scheduler.ts +3 -4
  60. package/src/index.ts +1 -5
  61. package/src/internal/clock.ts +2 -3
  62. package/src/internal/effect/circular.ts +13 -11
  63. package/src/internal/fiberRuntime.ts +13 -3
  64. package/src/internal/rateLimiter.ts +81 -19
  65. package/src/internal/version.ts +1 -1
  66. package/dist/cjs/internal/timeout.js +0 -24
  67. package/dist/cjs/internal/timeout.js.map +0 -1
  68. package/dist/dts/internal/timeout.d.ts +0 -7
  69. package/dist/dts/internal/timeout.d.ts.map +0 -1
  70. package/dist/esm/internal/timeout.js +0 -18
  71. package/dist/esm/internal/timeout.js.map +0 -1
  72. package/src/internal/timeout.ts +0 -23
package/src/FiberSet.ts CHANGED
@@ -26,7 +26,7 @@ export type TypeId = typeof TypeId
26
26
  * @since 2.0.0
27
27
  * @categories models
28
28
  */
29
- export interface FiberSet<out A, out E = never>
29
+ export interface FiberSet<out A = unknown, out E = unknown>
30
30
  extends Pipeable, Inspectable.Inspectable, Iterable<Fiber.RuntimeFiber<A, E>>
31
31
  {
32
32
  readonly [TypeId]: TypeId
@@ -92,7 +92,7 @@ const unsafeMake = <A, E>(): FiberSet<A, E> => {
92
92
  * @since 2.0.0
93
93
  * @categories constructors
94
94
  */
95
- export const make = <A, E = never>(): Effect.Effect<FiberSet<A, E>, never, Scope.Scope> =>
95
+ export const make = <A = unknown, E = unknown>(): Effect.Effect<FiberSet<A, E>, never, Scope.Scope> =>
96
96
  Effect.acquireRelease(Effect.sync(() => unsafeMake<A, E>()), clear)
97
97
 
98
98
  /**
@@ -101,7 +101,7 @@ export const make = <A, E = never>(): Effect.Effect<FiberSet<A, E>, never, Scope
101
101
  * @since 2.0.0
102
102
  * @categories constructors
103
103
  */
104
- export const makeRuntime = <A, E = never, R = never>(): Effect.Effect<
104
+ export const makeRuntime = <R = never, A = unknown, E = unknown>(): Effect.Effect<
105
105
  <XE extends E, XA extends A>(
106
106
  effect: Effect.Effect<XA, XE, R>,
107
107
  options?: Runtime.RunForkOptions | undefined
@@ -234,7 +234,7 @@ export const run: {
234
234
  * @since 2.0.0
235
235
  * @categories combinators
236
236
  */
237
- export const runtime: <A, E = never>(
237
+ export const runtime: <A, E>(
238
238
  self: FiberSet<A, E>
239
239
  ) => <R = never>() => Effect.Effect<
240
240
  <XE extends E, XA extends A>(
package/src/Option.ts CHANGED
@@ -648,12 +648,19 @@ export const flatMap: {
648
648
  export const andThen: {
649
649
  <A, B>(f: (a: A) => Option<B>): (self: Option<A>) => Option<B>
650
650
  <B>(f: Option<B>): <A>(self: Option<A>) => Option<B>
651
+ <A, B>(f: (a: A) => B): (self: Option<A>) => Option<B>
652
+ <B>(f: B): <A>(self: Option<A>) => Option<B>
651
653
  <A, B>(self: Option<A>, f: (a: A) => Option<B>): Option<B>
652
654
  <A, B>(self: Option<A>, f: Option<B>): Option<B>
655
+ <A, B>(self: Option<A>, f: (a: A) => B): Option<B>
656
+ <A, B>(self: Option<A>, f: B): Option<B>
653
657
  } = dual(
654
658
  2,
655
659
  <A, B>(self: Option<A>, f: (a: A) => Option<B> | Option<B>): Option<B> =>
656
- isFunction(f) ? flatMap(self, f) : flatMap(self, () => f)
660
+ flatMap(self, (a) => {
661
+ const b = isFunction(f) ? f(a) : f
662
+ return isOption(b) ? b : some(b)
663
+ })
657
664
  )
658
665
 
659
666
  /**
@@ -1,9 +1,5 @@
1
1
  /**
2
- * Limits the number of calls to a resource to a maximum amount in some interval using the token bucket algorithm.
3
- *
4
- * Note that only the moment of starting the effect is rate limited: the number of concurrent executions is not bounded.
5
- *
6
- * Calls are queued up in an unbounded queue until capacity becomes available.
2
+ * Limits the number of calls to a resource to a maximum amount in some interval.
7
3
  *
8
4
  * @since 2.0.0
9
5
  */
@@ -13,11 +9,10 @@ import * as internal from "./internal/rateLimiter.js"
13
9
  import type { Scope } from "./Scope.js"
14
10
 
15
11
  /**
16
- * Limits the number of calls to a resource to a maximum amount in some interval using the token bucket algorithm.
17
- *
18
- * Note that only the moment of starting the effect is rate limited: the number of concurrent executions is not bounded.
12
+ * Limits the number of calls to a resource to a maximum amount in some interval.
19
13
  *
20
- * Calls are queued up in an unbounded queue until capacity becomes available.
14
+ * Note that only the moment of starting the effect is rate limited: the number
15
+ * of concurrent executions is not bounded.
21
16
  *
22
17
  * @since 2.0.0
23
18
  * @category models
@@ -27,11 +22,113 @@ export interface RateLimiter {
27
22
  }
28
23
 
29
24
  /**
25
+ * @since 2.0.0
26
+ */
27
+ export declare namespace RateLimiter {
28
+ /**
29
+ * @since 2.0.0
30
+ * @category models
31
+ */
32
+ export interface Options {
33
+ /**
34
+ * The maximum number of requests that should be allowed.
35
+ */
36
+ readonly limit: number
37
+ /**
38
+ * The interval to utilize for rate-limiting requests. The semantics of the
39
+ * specified `interval` vary depending on the chosen `algorithm`:
40
+ *
41
+ * `token-bucket`: The maximum number of requests will be spread out over
42
+ * the provided interval if no tokens are available.
43
+ *
44
+ * For example, for a `RateLimiter` using the `token-bucket` algorithm with
45
+ * a `limit` of `10` and an `interval` of `1 seconds`, `1` request can be
46
+ * made every `100 millis`.
47
+ *
48
+ * `fixed-window`: The maximum number of requests will be reset during each
49
+ * interval. For example, for a `RateLimiter` using the `fixed-window`
50
+ * algorithm with a `limit` of `10` and an `interval` of `1 seconds`, a
51
+ * maximum of `10` requests can be made each second.
52
+ */
53
+ readonly interval: DurationInput
54
+ /**
55
+ * The algorithm to utilize for rate-limiting requests.
56
+ *
57
+ * Defaults to `token-bucket`.
58
+ */
59
+ readonly algorithm?: "fixed-window" | "token-bucket"
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Constructs a new `RateLimiter` which will utilize the specified algorithm
65
+ * to limit requests (defaults to `token-bucket`).
66
+ *
67
+ * Notes
68
+ * - Only the moment of starting the effect is rate limited. The number of concurrent executions is not bounded.
69
+ * - Instances of `RateLimiter` can be composed.
70
+ * - The "cost" per effect can be changed. See {@link withCost}
71
+ *
72
+ * @example
73
+ * import { Effect, RateLimiter } from "effect";
74
+ * import { compose } from "effect/Function"
75
+ *
76
+ * const program = Effect.scoped(
77
+ * Effect.gen(function* ($) {
78
+ * const perMinuteRL = yield* $(RateLimiter.make({ limit: 30, interval: "1 minutes" }))
79
+ * const perSecondRL = yield* $(RateLimiter.make({ limit: 2, interval: "1 seconds" }))
80
+ *
81
+ * // This rate limiter respects both the 30 calls per minute
82
+ * // and the 2 calls per second constraints.
83
+ * const rateLimit = compose(perMinuteRL, perSecondRL)
84
+ *
85
+ * // simulate repeated calls
86
+ * for (let n = 0; n < 100; n++) {
87
+ * // wrap the effect we want to limit with rateLimit
88
+ * yield* $(rateLimit(Effect.log("Calling RateLimited Effect")));
89
+ * }
90
+ * })
91
+ * );
92
+ *
30
93
  * @since 2.0.0
31
94
  * @category constructors
32
95
  */
33
- export const make: (limit: number, window: DurationInput) => Effect<
34
- RateLimiter,
35
- never,
36
- Scope
37
- > = internal.make
96
+ export const make: (options: RateLimiter.Options) => Effect<RateLimiter, never, Scope> = internal.make
97
+
98
+ /**
99
+ * Alters the per-effect cost of the rate-limiter.
100
+ *
101
+ * This can be used for "credit" based rate-limiting where different API endpoints
102
+ * cost a different number of credits within a time window.
103
+ * Eg: 1000 credits / hour, where a query costs 1 credit and a mutation costs 5 credits.
104
+ *
105
+ * @example
106
+ * import { Effect, RateLimiter } from "effect";
107
+ * import { compose } from "effect/Function";
108
+ *
109
+ * const program = Effect.scoped(
110
+ * Effect.gen(function* ($) {
111
+ * // Create a rate limiter that has an hourly limit of 1000 credits
112
+ * const rateLimiter = yield* $(RateLimiter.make({ limit: 1000, interval: "1 hours" }));
113
+ * // Query API costs 1 credit per call ( 1 is the default cost )
114
+ * const queryAPIRL = compose(rateLimiter, RateLimiter.withCost(1));
115
+ * // Mutation API costs 5 credits per call
116
+ * const mutationAPIRL = compose(rateLimiter, RateLimiter.withCost(5));
117
+
118
+ * // Use the pre-defined rate limiters
119
+ * yield* $(queryAPIRL(Effect.log("Sample Query")));
120
+ * yield* $(mutationAPIRL(Effect.log("Sample Mutation")));
121
+ *
122
+ * // Or set a cost on-the-fly
123
+ * yield* $(
124
+ * rateLimiter(Effect.log("Another query with a different cost")).pipe(
125
+ * RateLimiter.withCost(3)
126
+ * )
127
+ * );
128
+ * })
129
+ * );
130
+ *
131
+ * @since 2.0.0
132
+ * @category combinators
133
+ */
134
+ export const withCost: (cost: number) => <A, E, R>(effect: Effect<A, E, R>) => Effect<A, E, R> = internal.withCost
package/src/Scheduler.ts CHANGED
@@ -8,7 +8,6 @@ import type { FiberRef } from "./FiberRef.js"
8
8
  import { dual } from "./Function.js"
9
9
  import { globalValue } from "./GlobalValue.js"
10
10
  import * as core from "./internal/core.js"
11
- import * as timeout from "./internal/timeout.js"
12
11
 
13
12
  /**
14
13
  * @since 2.0.0
@@ -107,7 +106,7 @@ export class MixedScheduler implements Scheduler {
107
106
  */
108
107
  private starve(depth = 0) {
109
108
  if (depth >= this.maxNextTickBeforeTimer) {
110
- timeout.set(() => this.starveInternal(0), 0)
109
+ setTimeout(() => this.starveInternal(0), 0)
111
110
  } else {
112
111
  Promise.resolve(void 0).then(() => this.starveInternal(depth + 1))
113
112
  }
@@ -337,14 +336,14 @@ export const makeBatched = (
337
336
  * @category constructors
338
337
  */
339
338
  export const timer = (ms: number, shouldYield: Scheduler["shouldYield"] = defaultShouldYield) =>
340
- make((task) => timeout.set(task, ms), shouldYield)
339
+ make((task) => setTimeout(task, ms), shouldYield)
341
340
 
342
341
  /**
343
342
  * @since 2.0.0
344
343
  * @category constructors
345
344
  */
346
345
  export const timerBatched = (ms: number, shouldYield: Scheduler["shouldYield"] = defaultShouldYield) =>
347
- makeBatched((task) => timeout.set(task, ms), shouldYield)
346
+ makeBatched((task) => setTimeout(task, ms), shouldYield)
348
347
 
349
348
  /** @internal */
350
349
  export const currentScheduler: FiberRef<Scheduler> = globalValue(
package/src/index.ts CHANGED
@@ -545,11 +545,7 @@ export * as Queue from "./Queue.js"
545
545
  export * as Random from "./Random.js"
546
546
 
547
547
  /**
548
- * Limits the number of calls to a resource to a maximum amount in some interval using the token bucket algorithm.
549
- *
550
- * Note that only the moment of starting the effect is rate limited: the number of concurrent executions is not bounded.
551
- *
552
- * Calls are queued up in an unbounded queue until capacity becomes available.
548
+ * Limits the number of calls to a resource to a maximum amount in some interval.
553
549
  *
554
550
  * @since 2.0.0
555
551
  */
@@ -5,7 +5,6 @@ import type * as Effect from "../Effect.js"
5
5
  import * as Either from "../Either.js"
6
6
  import { constFalse } from "../Function.js"
7
7
  import * as core from "./core.js"
8
- import * as timeout from "./timeout.js"
9
8
 
10
9
  /** @internal */
11
10
  const ClockSymbolKey = "effect/Clock"
@@ -29,12 +28,12 @@ export const globalClockScheduler: Clock.ClockScheduler = {
29
28
  return constFalse
30
29
  }
31
30
  let completed = false
32
- const handle = timeout.set(() => {
31
+ const handle = setTimeout(() => {
33
32
  completed = true
34
33
  task()
35
34
  }, millis)
36
35
  return () => {
37
- timeout.clear(handle)
36
+ clearTimeout(handle)
38
37
  return !completed
39
38
  }
40
39
  }
@@ -65,22 +65,24 @@ class Semaphore {
65
65
  return Either.right(core.succeed(n))
66
66
  })
67
67
 
68
- readonly updateTaken = (f: (n: number) => number): Effect.Effect<void> =>
68
+ readonly updateTaken = (f: (n: number) => number): Effect.Effect<number> =>
69
69
  core.withFiberRuntime((fiber) => {
70
70
  this.taken = f(this.taken)
71
- fiber.getFiberRef(currentScheduler).scheduleTask(() => {
72
- const iter = this.waiters.values()
73
- let item = iter.next()
74
- while (item.done === false && item.value() === true) {
75
- item = iter.next()
76
- }
77
- }, fiber.getFiberRef(core.currentSchedulingPriority))
78
- return core.unit
71
+ if (this.waiters.size > 0) {
72
+ fiber.getFiberRef(currentScheduler).scheduleTask(() => {
73
+ const iter = this.waiters.values()
74
+ let item = iter.next()
75
+ while (item.done === false && item.value() === true) {
76
+ item = iter.next()
77
+ }
78
+ }, fiber.getFiberRef(core.currentSchedulingPriority))
79
+ }
80
+ return core.succeed(this.free)
79
81
  })
80
82
 
81
- readonly release = (n: number): Effect.Effect<void> => this.updateTaken((taken) => taken - n)
83
+ readonly release = (n: number): Effect.Effect<number> => this.updateTaken((taken) => taken - n)
82
84
 
83
- readonly releaseAll: Effect.Effect<void> = this.updateTaken((_) => 0)
85
+ readonly releaseAll: Effect.Effect<number> = this.updateTaken((_) => 0)
84
86
 
85
87
  readonly withPermits = (n: number) => <R, E, A>(self: Effect.Effect<R, E, A>) =>
86
88
  core.uninterruptibleMask((restore) =>
@@ -2771,7 +2771,12 @@ export const zipLeftOptions = dual<
2771
2771
  ) => Effect.Effect<A, E | E2, R | R2>
2772
2772
  >(
2773
2773
  (args) => core.isEffect(args[1]),
2774
- (self, that, options) => zipWithOptions(self, that, (a, _) => a, options)
2774
+ (self, that, options) => {
2775
+ if (options?.concurrent !== true && (options?.batching === undefined || options.batching === false)) {
2776
+ return core.zipLeft(self, that)
2777
+ }
2778
+ return zipWithOptions(self, that, (a, _) => a, options)
2779
+ }
2775
2780
  )
2776
2781
 
2777
2782
  /** @internal */
@@ -2794,11 +2799,16 @@ export const zipRightOptions: {
2794
2799
  } = dual((args) => core.isEffect(args[1]), <A, E, R, A2, E2, R2>(
2795
2800
  self: Effect.Effect<A, E, R>,
2796
2801
  that: Effect.Effect<A2, E2, R2>,
2797
- options: {
2802
+ options?: {
2798
2803
  readonly concurrent?: boolean | undefined
2799
2804
  readonly batching?: boolean | "inherit" | undefined
2800
2805
  }
2801
- ): Effect.Effect<A2, E2 | E, R2 | R> => zipWithOptions(self, that, (_, b) => b, options))
2806
+ ): Effect.Effect<A2, E2 | E, R2 | R> => {
2807
+ if (options?.concurrent !== true && (options?.batching === undefined || options.batching === false)) {
2808
+ return core.zipRight(self, that)
2809
+ }
2810
+ return zipWithOptions(self, that, (_, b) => b, options)
2811
+ })
2802
2812
 
2803
2813
  /** @internal */
2804
2814
  export const zipWithOptions: {
@@ -1,30 +1,92 @@
1
1
  import type { DurationInput } from "../Duration.js"
2
+ import * as Duration from "../Duration.js"
2
3
  import * as Effect from "../Effect.js"
3
- import type { RateLimiter } from "../RateLimiter.js"
4
- import type { Scope } from "../Scope.js"
5
- import * as SynchronizedRef from "../SynchronizedRef.js"
4
+ import * as FiberRef from "../FiberRef.js"
5
+ import { globalValue } from "../GlobalValue.js"
6
+ import type * as RateLimiter from "../RateLimiter.js"
7
+ import type * as Scope from "../Scope.js"
6
8
 
7
9
  /** @internal */
8
- export const make = (limit: number, window: DurationInput): Effect.Effect<
9
- RateLimiter,
10
+ export const make = ({
11
+ algorithm = "token-bucket",
12
+ interval,
13
+ limit
14
+ }: RateLimiter.RateLimiter.Options): Effect.Effect<
15
+ RateLimiter.RateLimiter,
10
16
  never,
11
- Scope
17
+ Scope.Scope
18
+ > => {
19
+ switch (algorithm) {
20
+ case "fixed-window": {
21
+ return fixedWindow(limit, interval)
22
+ }
23
+ case "token-bucket": {
24
+ return tokenBucket(limit, interval)
25
+ }
26
+ }
27
+ }
28
+
29
+ const tokenBucket = (limit: number, window: DurationInput): Effect.Effect<
30
+ RateLimiter.RateLimiter,
31
+ never,
32
+ Scope.Scope
12
33
  > =>
13
34
  Effect.gen(function*(_) {
14
- const scope = yield* _(Effect.scope)
35
+ const millisPerToken = Math.ceil(Duration.toMillis(window) / limit)
15
36
  const semaphore = yield* _(Effect.makeSemaphore(limit))
16
- const ref = yield* _(SynchronizedRef.make(false))
17
- const reset = SynchronizedRef.updateEffect(
18
- ref,
19
- (running) =>
20
- running ? Effect.succeed(true) : Effect.sleep(window).pipe(
21
- Effect.zipRight(SynchronizedRef.set(ref, false)),
22
- Effect.zipRight(semaphore.releaseAll),
23
- Effect.forkIn(scope),
24
- Effect.interruptible,
25
- Effect.as(true)
26
- )
37
+ const latch = yield* _(Effect.makeSemaphore(0))
38
+ const refill: Effect.Effect<void> = Effect.sleep(millisPerToken).pipe(
39
+ Effect.zipRight(latch.releaseAll),
40
+ Effect.zipRight(semaphore.release(1)),
41
+ Effect.flatMap((free) => free === limit ? Effect.unit : refill)
42
+ )
43
+ yield* _(
44
+ latch.take(1),
45
+ Effect.zipRight(refill),
46
+ Effect.forever,
47
+ Effect.forkScoped,
48
+ Effect.interruptible
49
+ )
50
+ const take = Effect.uninterruptibleMask((restore) =>
51
+ Effect.flatMap(
52
+ FiberRef.get(currentCost),
53
+ (cost) => Effect.zipRight(restore(semaphore.take(cost)), latch.release(1))
54
+ )
27
55
  )
28
- const take = Effect.zipRight(semaphore.take(1), reset)
29
56
  return (effect) => Effect.zipRight(take, effect)
30
57
  })
58
+
59
+ const fixedWindow = (limit: number, window: DurationInput): Effect.Effect<
60
+ RateLimiter.RateLimiter,
61
+ never,
62
+ Scope.Scope
63
+ > =>
64
+ Effect.gen(function*(_) {
65
+ const semaphore = yield* _(Effect.makeSemaphore(limit))
66
+ const latch = yield* _(Effect.makeSemaphore(0))
67
+ yield* _(
68
+ latch.take(1),
69
+ Effect.zipRight(Effect.sleep(window)),
70
+ Effect.zipRight(latch.releaseAll),
71
+ Effect.zipRight(semaphore.releaseAll),
72
+ Effect.forever,
73
+ Effect.forkScoped,
74
+ Effect.interruptible
75
+ )
76
+ const take = Effect.uninterruptibleMask((restore) =>
77
+ Effect.flatMap(
78
+ FiberRef.get(currentCost),
79
+ (cost) => Effect.zipRight(restore(semaphore.take(cost)), latch.release(1))
80
+ )
81
+ )
82
+ return (effect) => Effect.zipRight(take, effect)
83
+ })
84
+
85
+ /** @internal */
86
+ const currentCost = globalValue(
87
+ Symbol.for("effect/RateLimiter/currentCost"),
88
+ () => FiberRef.unsafeMake(1)
89
+ )
90
+
91
+ /** @internal */
92
+ export const withCost = (cost: number) => Effect.locally(currentCost, cost)
@@ -1 +1 @@
1
- export const moduleVersion = "2.3.1"
1
+ export const moduleVersion = "2.3.3"
@@ -1,24 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.set = exports.clear = void 0;
7
- /**
8
- * Bun currently has a bug where `setTimeout` doesn't behave correctly with a 0ms delay.
9
- *
10
- * @see https://github.com/oven-sh/bun/issues/3333
11
- */
12
- /** @internal */
13
- const isBun = typeof process === "undefined" ? false : !!process?.isBun;
14
- /** @internal */
15
- const clear = exports.clear = isBun ? id => clearInterval(id) : id => clearTimeout(id);
16
- /** @internal */
17
- const set = exports.set = isBun ? (fn, ms) => {
18
- const id = setInterval(() => {
19
- fn();
20
- clearInterval(id);
21
- }, ms);
22
- return id;
23
- } : (fn, ms) => setTimeout(fn, ms);
24
- //# sourceMappingURL=timeout.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"timeout.js","names":["isBun","process","clear","exports","id","clearInterval","clearTimeout","set","fn","ms","setInterval","setTimeout"],"sources":["../../../src/internal/timeout.ts"],"sourcesContent":[null],"mappings":";;;;;;AAAA;;;;;AAMA;AACA,MAAMA,KAAK,GAAG,OAAOC,OAAO,KAAK,WAAW,GAAG,KAAK,GAAG,CAAC,CAAGA,OAAe,EAAED,KAAM;AAElF;AACO,MAAME,KAAK,GAAAC,OAAA,CAAAD,KAAA,GAAiCF,KAAK,GAAII,EAAE,IAAKC,aAAa,CAACD,EAAE,CAAC,GAAIA,EAAE,IAAKE,YAAY,CAACF,EAAE,CAAC;AAE/G;AACO,MAAMG,GAAG,GAAAJ,OAAA,CAAAI,GAAA,GAAmDP,KAAK,GACtE,CAACQ,EAAc,EAAEC,EAAU,KAAI;EAC7B,MAAML,EAAE,GAAGM,WAAW,CAAC,MAAK;IAC1BF,EAAE,EAAE;IACJH,aAAa,CAACD,EAAE,CAAC;EACnB,CAAC,EAAEK,EAAE,CAAC;EAEN,OAAOL,EAAE;AACX,CAAC,GACD,CAACI,EAAc,EAAEC,EAAU,KAAKE,UAAU,CAACH,EAAE,EAAEC,EAAE,CAAC"}
@@ -1,7 +0,0 @@
1
- /**
2
- * Bun currently has a bug where `setTimeout` doesn't behave correctly with a 0ms delay.
3
- *
4
- * @see https://github.com/oven-sh/bun/issues/3333
5
- */
6
- export {};
7
- //# sourceMappingURL=timeout.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"timeout.d.ts","sourceRoot":"","sources":["../../../src/internal/timeout.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -1,18 +0,0 @@
1
- /**
2
- * Bun currently has a bug where `setTimeout` doesn't behave correctly with a 0ms delay.
3
- *
4
- * @see https://github.com/oven-sh/bun/issues/3333
5
- */
6
- /** @internal */
7
- const isBun = typeof process === "undefined" ? false : !!process?.isBun;
8
- /** @internal */
9
- export const clear = isBun ? id => clearInterval(id) : id => clearTimeout(id);
10
- /** @internal */
11
- export const set = isBun ? (fn, ms) => {
12
- const id = setInterval(() => {
13
- fn();
14
- clearInterval(id);
15
- }, ms);
16
- return id;
17
- } : (fn, ms) => setTimeout(fn, ms);
18
- //# sourceMappingURL=timeout.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"timeout.js","names":["isBun","process","clear","id","clearInterval","clearTimeout","set","fn","ms","setInterval","setTimeout"],"sources":["../../../src/internal/timeout.ts"],"sourcesContent":[null],"mappings":"AAAA;;;;;AAMA;AACA,MAAMA,KAAK,GAAG,OAAOC,OAAO,KAAK,WAAW,GAAG,KAAK,GAAG,CAAC,CAAGA,OAAe,EAAED,KAAM;AAElF;AACA,OAAO,MAAME,KAAK,GAAiCF,KAAK,GAAIG,EAAE,IAAKC,aAAa,CAACD,EAAE,CAAC,GAAIA,EAAE,IAAKE,YAAY,CAACF,EAAE,CAAC;AAE/G;AACA,OAAO,MAAMG,GAAG,GAAmDN,KAAK,GACtE,CAACO,EAAc,EAAEC,EAAU,KAAI;EAC7B,MAAML,EAAE,GAAGM,WAAW,CAAC,MAAK;IAC1BF,EAAE,EAAE;IACJH,aAAa,CAACD,EAAE,CAAC;EACnB,CAAC,EAAEK,EAAE,CAAC;EAEN,OAAOL,EAAE;AACX,CAAC,GACD,CAACI,EAAc,EAAEC,EAAU,KAAKE,UAAU,CAACH,EAAE,EAAEC,EAAE,CAAC"}
@@ -1,23 +0,0 @@
1
- /**
2
- * Bun currently has a bug where `setTimeout` doesn't behave correctly with a 0ms delay.
3
- *
4
- * @see https://github.com/oven-sh/bun/issues/3333
5
- */
6
-
7
- /** @internal */
8
- const isBun = typeof process === "undefined" ? false : !!((process as any)?.isBun)
9
-
10
- /** @internal */
11
- export const clear: (id: NodeJS.Timeout) => void = isBun ? (id) => clearInterval(id) : (id) => clearTimeout(id)
12
-
13
- /** @internal */
14
- export const set: (fn: () => void, ms: number) => NodeJS.Timeout = isBun ?
15
- (fn: () => void, ms: number) => {
16
- const id = setInterval(() => {
17
- fn()
18
- clearInterval(id)
19
- }, ms)
20
-
21
- return id
22
- } :
23
- (fn: () => void, ms: number) => setTimeout(fn, ms)