@@ -32,6 +32,28 @@ type logger = {
3232@@warning ("-30" ) // Duplicated type names (input)
3333@genType.import (("./Types.ts" , "Effect" ))
3434type rec effect <'input , 'output >
35+ @genType @unboxed
36+ and rateLimitDuration =
37+ | @as ("second" ) Second
38+ | @as ("minute" ) Minute
39+ | Milliseconds (int )
40+ @genType @unboxed
41+ and rateLimit =
42+ | @as (false ) Disable
43+ | Enable ({calls : int , per : rateLimitDuration })
44+ @genType
45+ and experimental_effectOptions <'input , 'output > = {
46+ /** The name of the effect. Used for logging and debugging. */
47+ name : string ,
48+ /** The input schema of the effect. */
49+ input : S .t <'input >,
50+ /** The output schema of the effect. */
51+ output : S .t <'output >,
52+ /** Rate limit for the effect. Set to false to disable or provide {calls: number, per: "second" | "minute"} to enable. */
53+ rateLimit ?: rateLimit ,
54+ /** Whether the effect should be cached. */
55+ cache ?: bool ,
56+ }
3557@genType
3658and effectOptions <'input , 'output > = {
3759 /** The name of the effect. Used for logging and debugging. */
@@ -40,13 +62,16 @@ and effectOptions<'input, 'output> = {
4062 input : S .t <'input >,
4163 /** The output schema of the effect. */
4264 output : S .t <'output >,
65+ /** Rate limit for the effect. Set to false to disable or provide {calls: number, per: "second" | "minute"} to enable. */
66+ rateLimit : rateLimit ,
4367 /** Whether the effect should be cached. */
4468 cache ?: bool ,
4569}
4670@genType.import (("./Types.ts" , "EffectContext" ))
4771and effectContext = {
4872 log : logger ,
4973 effect : 'input 'output . (effect <'input , 'output >, 'input ) => promise <'output >,
74+ mutable cache : bool ,
5075}
5176@genType
5277and effectArgs <'input > = {
@@ -55,12 +80,23 @@ and effectArgs<'input> = {
5580}
5681@@warning ("+30" )
5782
58- let experimental_createEffect = (
83+ let durationToMs = (duration : rateLimitDuration ) =>
84+ switch duration {
85+ | Second => 1000
86+ | Minute => 60000
87+ | Milliseconds (ms ) => ms
88+ }
89+
90+ let createEffect = (
5991 options : effectOptions <'input , 'output >,
6092 handler : effectArgs <'input > => promise <'output >,
6193) => {
6294 let outputSchema =
6395 S .schema (_ => options .output )-> (Utils .magic : S .t <S .t <'output >> => S .t <Internal .effectOutput >)
96+ let itemSchema = S .schema ((s ): Internal .effectCacheItem => {
97+ id : s .matches (S .string ),
98+ output : s .matches (outputSchema ),
99+ })
64100 {
65101 name : options .name ,
66102 handler : handler -> (
@@ -78,20 +114,48 @@ let experimental_createEffect = (
78114 Utils .magic : S .t <S .t <'input >> => S .t <Internal .effectInput >
79115 ),
80116 output : outputSchema ,
81- cache : switch options .cache {
82- | Some (true ) =>
83- let itemSchema = S .schema ((s ): Internal .effectCacheItem => {
84- id : s .matches (S .string ),
85- output : s .matches (outputSchema ),
86- })
117+ storageMeta : {
118+ table : Internal .makeCacheTable (~effectName = options .name ),
119+ outputSchema ,
120+ itemSchema ,
121+ },
122+ defaultShouldCache : switch options .cache {
123+ | Some (true ) => true
124+ | _ => false
125+ },
126+ rateLimit : switch options .rateLimit {
127+ | Disable => None
128+ | Enable ({calls , per }) =>
87129 Some ({
88- table : Internal .makeCacheTable (~effectName = options .name ),
89- outputSchema ,
90- itemSchema ,
130+ callsPerDuration : calls ,
131+ durationMs : per -> durationToMs ,
132+ availableCalls : calls ,
133+ windowStartTime : Js .Date .now (),
134+ queueCount : 0 ,
135+ nextWindowPromise : None ,
91136 })
92- | None
93- | Some (false ) =>
94- None
95137 },
96138 }-> (Utils .magic : Internal .effect => effect <'input , 'output >)
97139}
140+
141+ @deprecated (
142+ "Use createEffect instead. The only difference is that rateLimit option becomes required. Set it to false to keep the same behaviour."
143+ )
144+ let experimental_createEffect = (
145+ options : experimental_effectOptions <'input , 'output >,
146+ handler : effectArgs <'input > => promise <'output >,
147+ ) => {
148+ createEffect (
149+ {
150+ name : options .name ,
151+ input : options .input ,
152+ output : options .output ,
153+ rateLimit : switch options .rateLimit {
154+ | Some (rateLimit ) => rateLimit
155+ | None => Disable
156+ },
157+ cache : ?options .cache ,
158+ },
159+ handler ,
160+ )
161+ }
0 commit comments