Created
April 9, 2016 15:28
-
-
Save cb372/235754f3a9e6372101906b3023a6d7db to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Experiment into making ScalaCache generic in the serialization target. | |
* | |
* The idea is that different cache implementations can specify different serialization targets. | |
* Memcached/Redis would have Repr = Array[Byte], | |
* while in-memory caches (which don't need serialization) would have Repr = NoSerialization. | |
* | |
* The serialization target is encoded as a type parameter in `Cache` and `ScalaCache`. | |
* I tried it using a type member instead, but it turned into a bloodbath | |
* (you can see the first steps in https://gist.github.com/cb372/b53a0b51974f78212d3e06bdc682e977) | |
* | |
* We would provide the following default codecs implicitly: | |
* - [A, Array[Byte]] for all primitive A (Int, Double, ... ) | |
* - [A <: Serializable, Array[Byte]] | |
* - [A, NoSerialization] for any A (a dummy codec that will never be used) | |
*/ | |
object Demo { | |
sealed trait NoSerialization // the dummy serialization target for in-memory caches | |
trait Cache[Repr] { | |
def put[T](value: T)(implicit codec: Codec[T, Repr]): Unit | |
} | |
class CaffeineCache extends Cache[NoSerialization] { | |
def put[T](value: T)(implicit codec: Codec[T, NoSerialization]): Unit = { | |
println("I don't need to serialize anything") | |
// put the value in the cache | |
} | |
} | |
class MemcachedCache extends Cache[String] { // this would be Cache[Array[Byte]] | |
def put[T](t: T)(implicit codec: Codec[T, String]): Unit = { | |
val serialized = codec.serialize(t) | |
println(s"Serialized value: $serialized") | |
// put the value in the cache | |
} | |
} | |
trait ScalaCache[Repr] { | |
def cache: Cache[Repr] | |
} | |
object ScalaCache { | |
def apply[Repr](c: Cache[Repr]) = new ScalaCache[Repr] { | |
val cache = c | |
} | |
} | |
trait Codec[A, Repr] { | |
def serialize(value: A): Repr | |
} | |
object Codec { | |
implicit def anyToNoSerialization[A] = new Codec[A, NoSerialization] { | |
def serialize(value: A): NoSerialization = ??? // This will never be called | |
} | |
implicit val intToString = new Codec[Int, String] { | |
def serialize(value: Int): String = s"Int as a String: $value" | |
} | |
} | |
// in the scalacache package object | |
def put[T, Repr](t: T)(implicit scalaCache: ScalaCache[Repr], codec: Codec[T, Repr]): Unit = { | |
scalaCache.cache.put(t) | |
} | |
def main(args: Array[String]) = { | |
{ | |
implicit val scalaCache = ScalaCache.apply(new MemcachedCache) | |
put(23) // prints "Serialized value: Int as a String: 23" | |
} | |
{ | |
implicit val scalaCache = ScalaCache.apply(new CaffeineCache) | |
put(23) // prints "I don't need to serialize anything" | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment