Skip to content

Commit

Permalink
reduce churn of RcMap idle timeout fiber (#4282)
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart authored and effect-bot committed Jan 17, 2025
1 parent a9f2c0e commit 55e7ad5
Showing 1 changed file with 11 additions and 22 deletions.
33 changes: 11 additions & 22 deletions packages/effect/src/internal/rcMap.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type * as Cause from "../Cause.js"
import type { Clock } from "../Clock.js"
import * as Context from "../Context.js"
import type * as Deferred from "../Deferred.js"
import * as Duration from "../Duration.js"
Expand Down Expand Up @@ -139,7 +138,6 @@ const getImpl = core.fnUntraced(function*<K, A, E>(self: RcMapImpl<K, A, E>, key
if (o._tag === "Some") {
entry = o.value
entry.refCount++
if (entry.fiber) yield* core.interruptFiber(entry.fiber)
} else if (Number.isFinite(self.capacity) && MutableHashMap.size(self.state.map) >= self.capacity) {
return yield* core.fail(
new core.ExceededCapacityException(`RcMap attempted to exceed capacity of ${self.capacity}`)
Expand Down Expand Up @@ -197,17 +195,18 @@ const release = <K, A, E>(self: RcMapImpl<K, A, E>, key: K, entry: State.Entry<A
}

entry.expiresAt = clock.unsafeCurrentTimeMillis() + Duration.toMillis(self.idleTimeToLive)
if (entry.fiber) return core.void

return clock.sleep(self.idleTimeToLive).pipe(
core.zipRight(waitUntilExpired(entry, clock)),
core.interruptible,
core.zipRight(core.suspend(() => {
if (self.state._tag === "Open" && entry.refCount === 0) {
MutableHashMap.remove(self.state.map, key)
return core.scopeClose(entry.scope, core.exitVoid)
}
return core.void
})),
return core.interruptibleMask(function loop(restore): Effect<void> {
const now = clock.unsafeCurrentTimeMillis()
const remaining = entry.expiresAt - now
if (remaining <= 0) {
if (self.state._tag === "Closed" || entry.refCount > 0) return core.void
MutableHashMap.remove(self.state.map, key)
return restore(core.scopeClose(entry.scope, core.exitVoid))
}
return core.flatMap(clock.sleep(Duration.millis(remaining)), () => loop(restore))
}).pipe(
fiberRuntime.ensuring(core.sync(() => {
entry.fiber = undefined
})),
Expand All @@ -219,16 +218,6 @@ const release = <K, A, E>(self: RcMapImpl<K, A, E>, key: K, entry: State.Entry<A
)
})

const waitUntilExpired = <A, E>(entry: State.Entry<A, E>, clock: Clock) =>
core.suspend(function loop(): Effect<void> {
const now = clock.unsafeCurrentTimeMillis()
const remaining = entry.expiresAt - now
if (remaining <= 0) {
return core.void
}
return core.flatMap(clock.sleep(Duration.millis(remaining)), loop)
})

/** @internal */
export const keys = <K, A, E>(self: RcMap.RcMap<K, A, E>): Effect<Array<K>> => {
const impl = self as RcMapImpl<K, A, E>
Expand Down

0 comments on commit 55e7ad5

Please sign in to comment.