@@ -102,176 +102,178 @@ object Cache {
102
102
)(
103
103
timeToLive : Exit [Error , Value ] => Duration
104
104
)(implicit trace : ZTraceElement ): URIO [Environment , Cache [Key , Error , Value ]] =
105
- ZIO .environment[Environment ].flatMap { environment =>
106
- ZIO .fiberId.map { fiberId =>
107
- val cacheState = CacheState .initial[Key , Error , Value ]()
108
- import cacheState ._
109
-
110
- def trackAccess (key : MapKey [Key ]): Unit = {
111
- accesses.offer(key)
112
- if (updating.compareAndSet(false , true )) {
113
- var loop = true
114
- while (loop) {
115
- val key = accesses.poll(null )
116
- if (key ne null ) {
117
- keys.add(key)
118
- } else {
119
- loop = false
105
+ ZIO .clock.flatMap { clock =>
106
+ ZIO .environment[Environment ].flatMap { environment =>
107
+ ZIO .fiberId.map { fiberId =>
108
+ val cacheState = CacheState .initial[Key , Error , Value ]()
109
+ import cacheState ._
110
+
111
+ def trackAccess (key : MapKey [Key ]): Unit = {
112
+ accesses.offer(key)
113
+ if (updating.compareAndSet(false , true )) {
114
+ var loop = true
115
+ while (loop) {
116
+ val key = accesses.poll(null )
117
+ if (key ne null ) {
118
+ keys.add(key)
119
+ } else {
120
+ loop = false
121
+ }
120
122
}
121
- }
122
- var size = map.size
123
- loop = size > capacity
124
- while (loop) {
125
- val key = keys.remove()
126
- if (key ne null ) {
127
- if (map.remove(key.value) ne null ) {
128
- size -= 1
129
- loop = size > capacity
123
+ var size = map.size
124
+ loop = size > capacity
125
+ while (loop) {
126
+ val key = keys.remove()
127
+ if (key ne null ) {
128
+ if (map.remove(key.value) ne null ) {
129
+ size -= 1
130
+ loop = size > capacity
131
+ }
132
+ } else {
133
+ loop = false
130
134
}
131
- } else {
132
- loop = false
133
135
}
136
+ updating.set(false )
134
137
}
135
- updating.set(false )
136
138
}
137
- }
138
-
139
- def trackHit (): Unit =
140
- hits.increment()
141
-
142
- def trackMiss (): Unit =
143
- misses.increment()
144
-
145
- new Cache [Key , Error , Value ] {
146
-
147
- override def cacheStats (implicit trace : ZTraceElement ): UIO [CacheStats ] =
148
- ZIO .succeed(CacheStats (hits.longValue, misses.longValue, map.size))
149
139
150
- override def contains (k : Key )(implicit trace : ZTraceElement ): UIO [Boolean ] =
151
- ZIO .succeed(map.containsKey(k))
152
-
153
- override def entryStats (k : Key )(implicit trace : ZTraceElement ): UIO [Option [EntryStats ]] =
154
- ZIO .succeed {
155
- val value = map.get(k)
156
- if (value eq null ) None
157
- else {
158
- value match {
159
- case MapValue .Pending (_, _) =>
160
- None
161
- case MapValue .Complete (_, _, entryState, _) =>
162
- Option (EntryStats (entryState.loaded))
163
- case MapValue .Refreshing (_, MapValue .Complete (_, _, entryState, _)) =>
164
- Option (EntryStats (entryState.loaded))
140
+ def trackHit (): Unit =
141
+ hits.increment()
142
+
143
+ def trackMiss (): Unit =
144
+ misses.increment()
145
+
146
+ new Cache [Key , Error , Value ] {
147
+
148
+ override def cacheStats (implicit trace : ZTraceElement ): UIO [CacheStats ] =
149
+ ZIO .succeed(CacheStats (hits.longValue, misses.longValue, map.size))
150
+
151
+ override def contains (k : Key )(implicit trace : ZTraceElement ): UIO [Boolean ] =
152
+ ZIO .succeed(map.containsKey(k))
153
+
154
+ override def entryStats (k : Key )(implicit trace : ZTraceElement ): UIO [Option [EntryStats ]] =
155
+ ZIO .succeed {
156
+ val value = map.get(k)
157
+ if (value eq null ) None
158
+ else {
159
+ value match {
160
+ case MapValue .Pending (_, _) =>
161
+ None
162
+ case MapValue .Complete (_, _, entryState, _) =>
163
+ Option (EntryStats (entryState.loaded))
164
+ case MapValue .Refreshing (_, MapValue .Complete (_, _, entryState, _)) =>
165
+ Option (EntryStats (entryState.loaded))
166
+ }
165
167
}
166
168
}
167
- }
168
169
169
- override def get (k : Key )(implicit trace : ZTraceElement ): IO [Error , Value ] =
170
- ZIO .suspendSucceed {
171
- var key : MapKey [Key ] = null
172
- var promise : Promise [Error , Value ] = null
173
- var value = map.get(k)
174
- if (value eq null ) {
175
- promise = newPromise()
176
- key = new MapKey (k)
177
- value = map.putIfAbsent(k, MapValue .Pending (key, promise))
178
- }
179
- if (value eq null ) {
180
- trackAccess(key)
181
- trackMiss()
182
- lookupValueOf(k, promise)
183
- } else {
184
- value match {
185
- case MapValue .Pending (key, promise) =>
186
- trackAccess(key)
187
- trackHit()
188
- promise.await
189
- case MapValue .Complete (key, exit, _, timeToLive) =>
190
- trackAccess(key)
191
- trackHit()
192
- if (hasExpired(timeToLive)) {
193
- map.remove(k, value)
194
- get(k)
195
- } else {
196
- ZIO .done(exit)
197
- }
198
- case MapValue .Refreshing (
199
- promiseInProgress,
200
- MapValue .Complete (mapKey, currentResult, _, ttl)
201
- ) =>
202
- trackAccess(mapKey)
203
- trackHit()
204
- if (hasExpired(ttl)) {
205
- promiseInProgress.await
206
- } else {
207
- ZIO .done(currentResult)
208
- }
170
+ override def get (k : Key )(implicit trace : ZTraceElement ): IO [Error , Value ] =
171
+ ZIO .suspendSucceed {
172
+ var key : MapKey [Key ] = null
173
+ var promise : Promise [Error , Value ] = null
174
+ var value = map.get(k)
175
+ if (value eq null ) {
176
+ promise = newPromise()
177
+ key = new MapKey (k)
178
+ value = map.putIfAbsent(k, MapValue .Pending (key, promise))
179
+ }
180
+ if (value eq null ) {
181
+ trackAccess(key)
182
+ trackMiss()
183
+ lookupValueOf(k, promise)
184
+ } else {
185
+ value match {
186
+ case MapValue .Pending (key, promise) =>
187
+ trackAccess(key)
188
+ trackHit()
189
+ promise.await
190
+ case MapValue .Complete (key, exit, _, timeToLive) =>
191
+ trackAccess(key)
192
+ trackHit()
193
+ if (hasExpired(timeToLive)) {
194
+ map.remove(k, value)
195
+ get(k)
196
+ } else {
197
+ ZIO .done(exit)
198
+ }
199
+ case MapValue .Refreshing (
200
+ promiseInProgress,
201
+ MapValue .Complete (mapKey, currentResult, _, ttl)
202
+ ) =>
203
+ trackAccess(mapKey)
204
+ trackHit()
205
+ if (hasExpired(ttl)) {
206
+ promiseInProgress.await
207
+ } else {
208
+ ZIO .done(currentResult)
209
+ }
210
+ }
209
211
}
210
212
}
211
- }
212
213
213
- override def refresh (k : Key ): IO [Error , Unit ] =
214
- ZIO .suspendSucceed {
215
- val promise = newPromise()
216
- var value = map.get(k)
217
- if (value eq null ) {
218
- value = map.putIfAbsent(k, MapValue .Pending (new MapKey (k), promise))
219
- }
220
- val result = if (value eq null ) {
221
- lookupValueOf(k, promise)
222
- } else {
223
- value match {
224
- case MapValue .Pending (_, promiseInProgress) =>
225
- promiseInProgress.await
226
- case completedResult @ MapValue .Complete (mapKey, _, _, ttl) =>
227
- if (hasExpired(ttl)) {
228
- map.remove(k, value)
229
- get(k)
230
- } else {
231
- // Only trigger the lookup if we're still the current value, `completedResult`
232
- lookupValueOf(mapKey.value, promise).when {
233
- map.replace(k, completedResult, MapValue .Refreshing (promise, completedResult))
214
+ override def refresh (k : Key ): IO [Error , Unit ] =
215
+ ZIO .suspendSucceed {
216
+ val promise = newPromise()
217
+ var value = map.get(k)
218
+ if (value eq null ) {
219
+ value = map.putIfAbsent(k, MapValue .Pending (new MapKey (k), promise))
220
+ }
221
+ val result = if (value eq null ) {
222
+ lookupValueOf(k, promise)
223
+ } else {
224
+ value match {
225
+ case MapValue .Pending (_, promiseInProgress) =>
226
+ promiseInProgress.await
227
+ case completedResult @ MapValue .Complete (mapKey, _, _, ttl) =>
228
+ if (hasExpired(ttl)) {
229
+ map.remove(k, value)
230
+ get(k)
231
+ } else {
232
+ // Only trigger the lookup if we're still the current value, `completedResult`
233
+ lookupValueOf(mapKey.value, promise).when {
234
+ map.replace(k, completedResult, MapValue .Refreshing (promise, completedResult))
235
+ }
234
236
}
235
- }
236
- case MapValue . Refreshing (promiseInProgress, _) =>
237
- promiseInProgress.await
237
+ case MapValue . Refreshing (promiseInProgress, _) =>
238
+ promiseInProgress.await
239
+ }
238
240
}
241
+ result.unit
239
242
}
240
- result.unit
241
- }
242
243
243
- override def invalidate (k : Key )(implicit trace : ZTraceElement ): UIO [Unit ] =
244
- ZIO .succeed {
245
- map.remove(k)
246
- ()
247
- }
244
+ override def invalidate (k : Key )(implicit trace : ZTraceElement ): UIO [Unit ] =
245
+ ZIO .succeed {
246
+ map.remove(k)
247
+ ()
248
+ }
248
249
249
- override def invalidateAll : UIO [Unit ] =
250
- ZIO .succeed {
251
- map.clear()
252
- }
250
+ override def invalidateAll : UIO [Unit ] =
251
+ ZIO .succeed {
252
+ map.clear()
253
+ }
253
254
254
- def size (implicit trace : ZTraceElement ): UIO [Int ] =
255
- ZIO .succeed(map.size)
255
+ def size (implicit trace : ZTraceElement ): UIO [Int ] =
256
+ ZIO .succeed(map.size)
256
257
257
- private def lookupValueOf (key : Key , promise : Promise [Error , Value ]): IO [Error , Value ] =
258
- lookup(key)
259
- .provideEnvironment(environment)
260
- .exit
261
- .flatMap { exit =>
262
- val now = Instant .now ()
263
- val entryStats = EntryStats (now)
258
+ private def lookupValueOf (key : Key , promise : Promise [Error , Value ]): IO [Error , Value ] =
259
+ lookup(key)
260
+ .provideEnvironment(environment)
261
+ .exit
262
+ .flatMap { exit =>
263
+ val now = clock.unsafeInstant ()
264
+ val entryStats = EntryStats (now)
264
265
265
- map.put(key, MapValue .Complete (new MapKey (key), exit, entryStats, now.plus(timeToLive(exit))))
266
- promise.done(exit) *> ZIO .done(exit)
267
- }
268
- .onInterrupt(promise.interrupt *> ZIO .succeed(map.remove(key)))
266
+ map.put(key, MapValue .Complete (new MapKey (key), exit, entryStats, now.plus(timeToLive(exit))))
267
+ promise.done(exit) *> ZIO .done(exit)
268
+ }
269
+ .onInterrupt(promise.interrupt *> ZIO .succeed(map.remove(key)))
269
270
270
- private def newPromise () =
271
- Promise .unsafeMake[Error , Value ](fiberId)
271
+ private def newPromise () =
272
+ Promise .unsafeMake[Error , Value ](fiberId)
272
273
273
- private def hasExpired (timeToLive : Instant ) =
274
- Instant .now().isAfter(timeToLive)
274
+ private def hasExpired (timeToLive : Instant ) =
275
+ clock.unsafeInstant().isAfter(timeToLive)
276
+ }
275
277
}
276
278
}
277
279
}
0 commit comments