@@ -4,7 +4,7 @@ import type * as Deferred from "../Deferred.js"
44import * as Duration from "../Duration.js"
55import type { Effect } from "../Effect.js"
66import type { RuntimeFiber } from "../Fiber.js"
7- import { dual , identity } from "../Function.js"
7+ import { constant , dual , flow , identity } from "../Function.js"
88import * as MutableHashMap from "../MutableHashMap.js"
99import { pipeArguments } from "../Pipeable.js"
1010import type * as RcMap from "../RcMap.js"
@@ -33,6 +33,7 @@ declare namespace State {
3333 readonly deferred : Deferred . Deferred < A , E >
3434 readonly scope : Scope . CloseableScope
3535 readonly finalizer : Effect < void >
36+ readonly idleTimeToLive : Duration . Duration
3637 fiber : RuntimeFiber < void , never > | undefined
3738 expiresAt : number
3839 refCount : number
@@ -58,7 +59,7 @@ class RcMapImpl<K, A, E> implements RcMap.RcMap<K, A, E> {
5859 readonly lookup : ( key : K ) => Effect < A , E , Scope . Scope > ,
5960 readonly context : Context . Context < never > ,
6061 readonly scope : Scope . Scope ,
61- readonly idleTimeToLive : Duration . Duration | undefined ,
62+ readonly idleTimeToLive : ( ( key : K ) => Duration . Duration ) | undefined ,
6263 readonly capacity : number
6364 ) {
6465 this [ TypeId ] = variance
@@ -73,27 +74,32 @@ class RcMapImpl<K, A, E> implements RcMap.RcMap<K, A, E> {
7374export const make : {
7475 < K , A , E , R > ( options : {
7576 readonly lookup : ( key : K ) => Effect < A , E , R >
76- readonly idleTimeToLive ?: Duration . DurationInput | undefined
77+ readonly idleTimeToLive ?: Duration . DurationInput | ( ( key : K ) => Duration . DurationInput ) | undefined
7778 readonly capacity ?: undefined
7879 } ) : Effect < RcMap . RcMap < K , A , E > , never , Scope . Scope | R >
7980 < K , A , E , R > ( options : {
8081 readonly lookup : ( key : K ) => Effect < A , E , R >
81- readonly idleTimeToLive ?: Duration . DurationInput | undefined
82+ readonly idleTimeToLive ?: Duration . DurationInput | ( ( key : K ) => Duration . DurationInput ) | undefined
8283 readonly capacity : number
8384 } ) : Effect < RcMap . RcMap < K , A , E | Cause . ExceededCapacityException > , never , Scope . Scope | R >
8485} = < K , A , E , R > ( options : {
8586 readonly lookup : ( key : K ) => Effect < A , E , R >
86- readonly idleTimeToLive ?: Duration . DurationInput | undefined
87+ readonly idleTimeToLive ?: Duration . DurationInput | ( ( key : K ) => Duration . DurationInput ) | undefined
8788 readonly capacity ?: number | undefined
8889} ) =>
8990 core . withFiberRuntime < RcMap . RcMap < K , A , E > , never , R | Scope . Scope > ( ( fiber ) => {
9091 const context = fiber . getFiberRef ( core . currentContext ) as Context . Context < R | Scope . Scope >
9192 const scope = Context . get ( context , fiberRuntime . scopeTag )
93+ const idleTimeToLive = options . idleTimeToLive === undefined
94+ ? undefined
95+ : typeof options . idleTimeToLive === "function"
96+ ? flow ( options . idleTimeToLive , Duration . decode )
97+ : constant ( Duration . decode ( options . idleTimeToLive ) )
9298 const self = new RcMapImpl < K , A , E > (
9399 options . lookup as any ,
94100 context ,
95101 scope ,
96- options . idleTimeToLive ? Duration . decode ( options . idleTimeToLive ) : undefined ,
102+ idleTimeToLive ,
97103 Math . max ( options . capacity ?? Number . POSITIVE_INFINITY , 0 )
98104 )
99105 return core . as (
@@ -169,10 +175,12 @@ const acquire = core.fnUntraced(function*<K, A, E>(self: RcMapImpl<K, A, E>, key
169175 core . flatMap ( ( exit ) => core . deferredDone ( deferred , exit ) ) ,
170176 circular . forkIn ( scope )
171177 )
178+ const idleTimeToLive = self . idleTimeToLive ? self . idleTimeToLive ( key ) : Duration . zero
172179 const entry : State . Entry < A , E > = {
173180 deferred,
174181 scope,
175182 finalizer : undefined as any ,
183+ idleTimeToLive,
176184 fiber : undefined ,
177185 expiresAt : 0 ,
178186 refCount : 1
@@ -192,19 +200,19 @@ const release = <K, A, E>(self: RcMapImpl<K, A, E>, key: K, entry: State.Entry<A
192200 } else if (
193201 self . state . _tag === "Closed"
194202 || ! MutableHashMap . has ( self . state . map , key )
195- || self . idleTimeToLive === undefined
203+ || Duration . isZero ( entry . idleTimeToLive )
196204 ) {
197205 if ( self . state . _tag === "Open" ) {
198206 MutableHashMap . remove ( self . state . map , key )
199207 }
200208 return core . scopeClose ( entry . scope , core . exitVoid )
201209 }
202210
203- if ( ! Duration . isFinite ( self . idleTimeToLive ) ) {
211+ if ( ! Duration . isFinite ( entry . idleTimeToLive ) ) {
204212 return core . void
205213 }
206214
207- entry . expiresAt = clock . unsafeCurrentTimeMillis ( ) + Duration . toMillis ( self . idleTimeToLive )
215+ entry . expiresAt = clock . unsafeCurrentTimeMillis ( ) + Duration . toMillis ( entry . idleTimeToLive )
208216 if ( entry . fiber ) return core . void
209217
210218 return core . interruptibleMask ( function loop ( restore ) : Effect < void > {
@@ -276,10 +284,12 @@ export const touch: {
276284 < K , A , E > ( self_ : RcMap . RcMap < K , A , E > , key : K ) =>
277285 coreEffect . clockWith ( ( clock ) => {
278286 const self = self_ as RcMapImpl < K , A , E >
279- if ( ! self . idleTimeToLive || self . state . _tag === "Closed" ) return core . void
287+ if ( self . state . _tag === "Closed" ) return core . void
280288 const o = MutableHashMap . get ( self . state . map , key )
281289 if ( o . _tag === "None" ) return core . void
282- o . value . expiresAt = clock . unsafeCurrentTimeMillis ( ) + Duration . toMillis ( self . idleTimeToLive )
290+ const entry = o . value
291+ if ( Duration . isZero ( entry . idleTimeToLive ) ) return core . void
292+ entry . expiresAt = clock . unsafeCurrentTimeMillis ( ) + Duration . toMillis ( entry . idleTimeToLive )
283293 return core . void
284294 } )
285295)
0 commit comments