aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/core/Refresh.scala
diff options
context:
space:
mode:
authorJakob Odersky <jakob@driver.xyz>2018-09-12 16:03:17 -0700
committerJakob Odersky <jakob@odersky.com>2018-10-09 16:19:39 -0700
commit616e62e733dbbd4e6bacc5f563deef534794dc9e (patch)
tree069d5cbb261793540700a1a7d04e4474806eb294 /src/main/scala/xyz/driver/core/Refresh.scala
parent7a793ffa068fda8f2146f84fa785328d928dba03 (diff)
downloaddriver-core-616e62e733dbbd4e6bacc5f563deef534794dc9e.tar.gz
driver-core-616e62e733dbbd4e6bacc5f563deef534794dc9e.tar.bz2
driver-core-616e62e733dbbd4e6bacc5f563deef534794dc9e.zip
Move reporting into separate project
Diffstat (limited to 'src/main/scala/xyz/driver/core/Refresh.scala')
-rw-r--r--src/main/scala/xyz/driver/core/Refresh.scala69
1 files changed, 0 insertions, 69 deletions
diff --git a/src/main/scala/xyz/driver/core/Refresh.scala b/src/main/scala/xyz/driver/core/Refresh.scala
deleted file mode 100644
index 6db9c26..0000000
--- a/src/main/scala/xyz/driver/core/Refresh.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-package xyz.driver.core
-
-import java.time.Instant
-import java.util.concurrent.atomic.AtomicReference
-
-import scala.concurrent.{ExecutionContext, Future, Promise}
-import scala.concurrent.duration.Duration
-
-/** A single-value asynchronous cache with TTL.
- *
- * Slightly adapted from
- * [[https://github.com/twitter/util/blob/ae0ab09134414438af9dfaa88a4613cecbff4741/util-cache/src/main/scala/com/twitter/cache/Refresh.scala
- * Twitter's "util" library]]
- *
- * Released under the Apache License 2.0.
- */
-object Refresh {
-
- /** Creates a function that will provide a cached value for a given time-to-live (TTL).
- *
- * It avoids the "thundering herd" problem if multiple requests arrive
- * simultanously and the cached value has expired or is unset.
- *
- * Usage example:
- * {{{
- * def freshToken(): Future[String] = // expensive network call to get an access token
- * val getToken: () => Future[String] = Refresh.every(1.hour)(freshToken())
- *
- * getToken() // new token is issued
- * getToken() // subsequent calls use the cached token
- * // wait 1 hour
- * getToken() // new token is issued
- * }}}
- *
- * @param ttl Time-To-Live duration to cache a computed value.
- * @param compute Call-by-name operation that eventually computes a value to
- * be cached. Note that if the computation (i.e. the future) fails, the value
- * is not cached.
- * @param ec The execution context in which valeu computations will be run.
- * @return A zero-arg function that returns the cached value.
- */
- def every[A](ttl: Duration)(compute: => Future[A])(implicit ec: ExecutionContext): () => Future[A] = {
- val ref = new AtomicReference[(Future[A], Instant)](
- (Future.failed(new NoSuchElementException("Cached value was never computed")), Instant.MIN)
- )
- def refresh(): Future[A] = {
- val tuple = ref.get
- val (cachedValue, lastRetrieved) = tuple
- val now = Instant.now
- if (now.getEpochSecond < lastRetrieved.getEpochSecond + ttl.toSeconds) {
- cachedValue
- } else {
- val p = Promise[A]
- val nextTuple = (p.future, now)
- if (ref.compareAndSet(tuple, nextTuple)) {
- compute.onComplete { done =>
- if (done.isFailure) {
- ref.set((p.future, lastRetrieved)) // don't update retrieval time in case of failure
- }
- p.complete(done)
- }
- }
- refresh()
- }
- }
- refresh _
- }
-
-}