All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.velocidi.apso.caching.Cache.scala Maven / Gradle / Ivy

/*
 * Copyright © 2011-2015 the spray project 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Copied from https://github.com/spray/spray/blob/master/spray-caching/src/main/scala/spray/caching/Cache.scala in
// order to be compiled against Scala 2.12.

package com.velocidi.apso.caching

import scala.concurrent.{ Promise, Future, ExecutionContext }
import scala.util.control.NonFatal

/**
 * General interface implemented by all spray cache implementations.
 */
trait Cache[V] { cache =>

  /**
   * Selects the (potentially non-existing) cache entry with the given key.
   */
  def apply(key: Any) = new Keyed(key)

  class Keyed(key: Any) {
    /**
     * Returns either the cached Future for the key or evaluates the given call-by-name argument
     * which produces either a value instance of type `V` or a `Future[V]`.
     */
    def apply(magnet: => ValueMagnet[V])(implicit ec: ExecutionContext): Future[V] =
      cache.apply(key, () => try magnet.future catch { case NonFatal(e) => Future.failed(e) })

    /**
     * Returns either the cached Future for the key or evaluates the given function which
     * should lead to eventual completion of the promise.
     */
    def apply[U](f: Promise[V] => U)(implicit ec: ExecutionContext): Future[V] =
      cache.apply(key, () => { val p = Promise[V](); f(p); p.future })
  }

  /**
   * Returns either the cached Future for the given key or evaluates the given value generating
   * function producing a `Future[V]`.
   */
  def apply(key: Any, genValue: () => Future[V])(implicit ec: ExecutionContext): Future[V]

  /**
   * Retrieves the future instance that is currently in the cache for the given key.
   * Returns None if the key has no corresponding cache entry.
   */
  def get(key: Any): Option[Future[V]]

  /**
   * Removes the cache item for the given key. Returns the removed item if it was found (and removed).
   */
  def remove(key: Any): Option[Future[V]]

  /**
   * Clears the cache by removing all entries.
   */
  def clear(): Unit

  /**
   * Returns the set of keys in the cache, in no particular order
   * Should return in roughly constant time.
   * Note that this number might not reflect the exact keys of active, unexpired
   * cache entries, since expired entries are only evicted upon next access
   * (or by being thrown out by a capacity constraint).
   */
  def keys: Set[Any]

  /**
   * Returns a snapshot view of the keys as an iterator, traversing the keys from the least likely
   * to be retained to the most likely.  Note that this is not constant time.
   * @param limit No more than limit keys will be returned
   */
  def ascendingKeys(limit: Option[Int] = None): Iterator[Any]

  /**
   * Returns the upper bound for the number of currently cached entries.
   * Note that this number might not reflect the exact number of active, unexpired
   * cache entries, since expired entries are only evicted upon next access
   * (or by being thrown out by a capacity constraint).
   */
  def size: Int
}

class ValueMagnet[V](val future: Future[V])
object ValueMagnet {
  implicit def fromAny[V](block: V): ValueMagnet[V] = fromFuture(Future.successful(block))
  implicit def fromFuture[V](future: Future[V]): ValueMagnet[V] = new ValueMagnet(future)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy