11import type * as Cause from "../Cause.js"
2+ import type { Clock } from "../Clock.js"
23import * as Context from "../Context.js"
34import type * as Deferred from "../Deferred.js"
45import * as Duration from "../Duration.js"
@@ -34,6 +35,7 @@ declare namespace State {
3435 readonly scope : Scope . CloseableScope
3536 readonly finalizer : Effect < void >
3637 fiber : RuntimeFiber < void , never > | undefined
38+ expiresAt : number
3739 refCount : number
3840 }
3941}
@@ -168,6 +170,7 @@ const acquire = core.fnUntraced(function*<K, A, E>(self: RcMapImpl<K, A, E>, key
168170 scope,
169171 finalizer : undefined as any ,
170172 fiber : undefined ,
173+ expiresAt : 0 ,
171174 refCount : 1
172175 }
173176 ; ( entry as any ) . finalizer = release ( self , key , entry )
@@ -178,7 +181,7 @@ const acquire = core.fnUntraced(function*<K, A, E>(self: RcMapImpl<K, A, E>, key
178181} )
179182
180183const release = < K , A , E > ( self : RcMapImpl < K , A , E > , key : K , entry : State . Entry < A , E > ) =>
181- core . suspend ( ( ) => {
184+ coreEffect . clockWith ( ( clock ) => {
182185 entry . refCount --
183186 if ( entry . refCount > 0 ) {
184187 return core . void
@@ -193,7 +196,10 @@ const release = <K, A, E>(self: RcMapImpl<K, A, E>, key: K, entry: State.Entry<A
193196 return core . scopeClose ( entry . scope , core . exitVoid )
194197 }
195198
196- return coreEffect . sleep ( self . idleTimeToLive ) . pipe (
199+ entry . expiresAt = clock . unsafeCurrentTimeMillis ( ) + Duration . toMillis ( self . idleTimeToLive )
200+
201+ return clock . sleep ( self . idleTimeToLive ) . pipe (
202+ core . zipRight ( waitUntilExpired ( entry , clock ) ) ,
197203 core . interruptible ,
198204 core . zipRight ( core . suspend ( ( ) => {
199205 if ( self . state . _tag === "Open" && entry . refCount === 0 ) {
@@ -213,6 +219,16 @@ const release = <K, A, E>(self: RcMapImpl<K, A, E>, key: K, entry: State.Entry<A
213219 )
214220 } )
215221
222+ const waitUntilExpired = < A , E > ( entry : State . Entry < A , E > , clock : Clock ) =>
223+ core . suspend ( function loop ( ) : Effect < void > {
224+ const now = clock . unsafeCurrentTimeMillis ( )
225+ const remaining = entry . expiresAt - now
226+ if ( remaining <= 0 ) {
227+ return core . void
228+ }
229+ return core . flatMap ( clock . sleep ( Duration . millis ( remaining ) ) , loop )
230+ } )
231+
216232/** @internal */
217233export const keys = < K , A , E > ( self : RcMap . RcMap < K , A , E > ) : Effect < Array < K > > => {
218234 const impl = self as RcMapImpl < K , A , E >
@@ -239,3 +255,20 @@ export const invalidate: {
239255 if ( entry . fiber ) yield * core . interruptFiber ( entry . fiber )
240256 } )
241257)
258+
259+ /** @internal */
260+ export const touch : {
261+ < K > ( key : K ) : < A , E > ( self : RcMap . RcMap < K , A , E > ) => Effect < void >
262+ < K , A , E > ( self : RcMap . RcMap < K , A , E > , key : K ) : Effect < void >
263+ } = dual (
264+ 2 ,
265+ < K , A , E > ( self_ : RcMap . RcMap < K , A , E > , key : K ) =>
266+ coreEffect . clockWith ( ( clock ) => {
267+ const self = self_ as RcMapImpl < K , A , E >
268+ if ( ! self . idleTimeToLive || self . state . _tag === "Closed" ) return core . void
269+ const o = MutableHashMap . get ( self . state . map , key )
270+ if ( o . _tag === "None" ) return core . void
271+ o . value . expiresAt = clock . unsafeCurrentTimeMillis ( ) + Duration . toMillis ( self . idleTimeToLive )
272+ return core . void
273+ } )
274+ )
0 commit comments