def andThen[K, V, V2, V3 >: V]()

in storehaus-core/src/main/scala/com/twitter/storehaus/ReadableStore.scala [116:169]


  def andThen[K, V, V2, V3 >: V](l: ReadableStore[K, V], r: ReadableStore[V3, V2])
      (implicit fc: FutureCollector): ReadableStore[K, V2] =
    new ComposedStore[K, V, V2, V3](l, r)

  /** unpivot or uncurry a ReadableStore which has a value that is a Map.
   * Often it is more efficient to pack values into inner maps, especially when you have very sparse
   * stores.  This allows you to work with such a packed store as though it was unpacked
   */
  def unpivot[K, OuterK, InnerK, V](store: ReadableStore[OuterK, Map[InnerK, V]])
    (split: K => (OuterK, InnerK)): ReadableStore[K, V] =
    new UnpivotedReadableStore(store)(split)

  /** Lazily change the key and value for a store.
   * This does not change the representation, only alters before going in or out of the store.
   */
  def convert[K1, K2, V1, V2](
      store: ReadableStore[K1, V1])(kfn: K2 => K1)(vfn: V1 => Future[V2]): ReadableStore[K2, V2] =
    new ConvertedReadableStore(store)(kfn)(vfn)

  /** Returns a new ReadableStore that caches reads from the underlying
   * store using the supplied mutable cache.  */
  def withCache[K, V](
      store: ReadableStore[K, V], cache: MutableCache[K, Future[Option[V]]]): ReadableStore[K, V] =
    new CachedReadableStore(store, cache)

  /** Returns a new ReadableStore that caches reads from the underlying
   * store using the supplied immutable cache.  */
  def withCache[K, V](
      store: ReadableStore[K, V], cache: Cache[K, Future[Option[V]]]): ReadableStore[K, V] =
    new CachedReadableStore(store, cache.toMutable())

  /**
   * Returns a ReadableStore[K, V] that attempts reads from a store
   * multiple times until a predicate is met. The iterable of backoffs
   * defines the time interval between two read attempts. If there is
   * not read result satisfying the given predicate after all read
   * attempts, a NotFoundException will be thrown.
   */
  def withRetry[K, V](
    store: ReadableStore[K, V], backoffs: Iterable[Duration]
  )(pred: Option[V] => Boolean)(implicit timer: Timer): ReadableStore[K, V] =
    new RetryingReadableStore(store, backoffs)(pred)
}

/** Main trait to represent asynchronous readable stores
 * Here you see the tri-state logic:
 * <ul>
 *   <li>Future(Some(v)) - The store has the item</li>
 *   <li>Future(None) -
 *    The store definitely DOES NOT have the item (not the same as no answer).</li>
 *   <li>Future.exception - Some kind of unexpected failure (including non-answer).</li>
 * </ul>
 */
trait ReadableStore[-K, +V] extends Closable { self =>