12. Java
object DBConnector {
val config = ConfigFactory.load()
val hosts = List(config.getString("aerospike.host"))
val port = config.getInt("aerospike.port")
val namespace = config.getString("aerospike.namespace")
val setName = config.getString("aerospike.setName")
val database: AsyncClient = new AsyncClient(new AsyncClientPolicy, hosts.map(new Host(_, port)): _*)
val key1 = new Key("namespace", "setName", new StringValue("key1"))
val key2 = new Key("namespace", "setName", new StringValue("key2"))
val key3 = new Key("namespace", "setName", new StringValue("key3"))
database.put(new WritePolicy, key1, Seq(new Bin("bin1", new StringValue("abcd"))): _*)
database.put(new WritePolicy, key2, Seq(new Bin("bin2", new IntegerValue(2))): _*)
database.put(new WritePolicy, key3, Seq(new Bin("bin3", new BooleanValue(true))): _*)
val record1 = database.get(new BatchPolicy, key1)
val record2 = database.get(new BatchPolicy, key2)
val record3 = database.get(new BatchPolicy, key3)
val res1 = longParsingFunction(record1)
val res2 = longParsingFunction(record2)
val res3 = longParsingFunction(record3)
def longParsingFunction[T](record: Record): T = {
val outValue: Map[String, Option[$tpe]] = {
val jMap = record.bins.view collect {
case (name, bt: Any) =>
val res = fetch(bt)
if (res.isEmpty && r.bins.nonEmpty) throw new Exception("Wrong type!")
else name -> res
13. Scalaobject DBConnector {
val db = new Database()
db.put("key1", "bin1", "abcd")
db.put("key2", "bin2", 2)
db.put("key3", "bin3", true)
val res1 = db.get[String]("key1")
val res2 = db.get[Int]("key2")
val res3 = db.get[Boolean]("key3")
}
15. package ru.tinkoff.example
object DBConnector {
…
database.put(new WritePolicy,
new Key("namespace", "setName", new StringValue("key1")),
Seq(new Bin("binName1", new StringValue("binValue"))):_*)
database.put(new WritePolicy,
new Key("namespace", "setName", new StringValue("key2")),
Seq(new Bin("binName2", new IntegerValue(2))):_*)
database.put(new WritePolicy,
new Key("namespace", "setName", new StringValue("key3")),
Seq(new Bin("binName3", new BooleanValue(true))):_*)
}
7 Key types
12 Bin types
24. public final class Record {
//Map of requested name/value bins.
public final Map<String,Object> bins;
public final int generation;
public final int expiration;
…
}
36. trait KeyWrapper[K] {
def apply(k: K): Key = new Key(toValue(k))
def toValue(v: K): Value = v match {
case s: String => new StringValue(s)
case h: HList => new MapValue(toMap(h))
…
}
}
47. trait BinWrapper[B] {
def apply(v: B): Bin = new Bin("name", toValue(v))
def toValue(v: B): Value = v match {
case s: String => new StringValue(s)
case h: HList => new MapValue(toMap(h))
case _ => throw new Exception("Wrong type")
}
def apply(r: Record): Map[String, B] =
r.bins.collect {
case (name, something) =>
name -> fetch(something)
}.toMap
def fetch(donkey: Any): B
}
48. trait BinWrapper[B] {
def apply(v: B): Bin = new Bin("name", toValue(v))
def toValue(v: B): Value = v match {
case s: String => new StringValue(s)
case h: HList => new MapValue(toMap(h))
case _ => throw new Exception("Wrong type")
}
def apply(r: Record): Map[String, B] =
r.bins.collect {
case (name, something) =>
name -> fetch(something)
}.toMap
def fetch(donkey: Any): B
}
51. val tpe = weakTypeOf[T]
val fetchValue = tpe match {
case t if t =:= weakTypeOf[String] =>
q""" def fetch(any: Any): $tpe = any match {
case v: String => v
case _ => throw new Exception("Wrong type")
} """
case t if isHList(t) =>
q""" def fetch(any: Any): $tpe = any match {
case mv: MapValue => mv.getObject match {
case m: Map[String, Any] =>
parse(m).toHList[$tpe].getOrElse{}
case _ => throw new Exception("Wrong type")
}
case _ => throw new Exception("Wrong type")
} """
...
}
52. Expr[ru.tinkoff.BinWrapper[shapeless.::[Int,shapeless.::[Boolean,shapeless.HNil]]]]({
import com.aerospike.client.{Key, Value};
import collection.JavaConversions._;
import com.aerospike.client.Value._;
import shapeless._;
import syntax.std.traversable._;
{
final class $anon extends BinWrapper[shapeless.::[Int,shapeless.::[Boolean,shapeless.HNil]]] {
def <init>() = {
super.<init>();
()
};
def fetch(any: Any): shapeless.::[Int,shapeless.::[Boolean,shapeless.HNil]] = any match {
case (mv @ (_: MapValue)) => mv.getObject match {
case (m @ (_: Map[String, Any])) =>
parse(m).toHList[shapeless.::[Int,shapeless.::[Boolean,shapeless.HNil]]].getOrElse{}
case _ => throw new Exception("Wrong type")
}
case _ => throw new Exception("Wrong type")
}
};
new $anon()
}
})
BinWrapper.matBin[Int::Boolean::HNil]
53. Expr[ru.tinkoff.BinWrapper[shapeless.::[Int,shapeless.::[Boolean,shapeless.HNil]]]]({
import com.aerospike.client.{Key, Value};
import collection.JavaConversions._;
import com.aerospike.client.Value._;
import shapeless._;
import syntax.std.traversable._;
{
final class $anon extends BinWrapper[shapeless.::[Int,shapeless.::[Boolean,shapeless.HNil]]] {
def <init>() = {
super.<init>();
()
};
def fetch(any: Any): shapeless.::[Int,shapeless.::[Boolean,shapeless.HNil]] = any match {
case (mv @ (_: MapValue)) => mv.getObject match {
case (m @ (_: Map[String, Any])) =>
parse(m).toHList[shapeless.::[Int,shapeless.::[Boolean,shapeless.HNil]]].getOrElse{}
case _ => throw new Exception("Wrong type")
}
case _ => throw new Exception("Wrong type")
}
};
new $anon()
}
})
}imports
def fetch: Any => HL
type HL = Int::Boolean::HNil
54.
55. def writeBin[B](b: B)
(implicit bw: BinWrapper[B]): Bin = bw(b)
val asMap = new BinWrapper[Truck] { }
val asJson = new BinWrapper[Truck] { … }
writeBin("tr1", Truck("truck1", 4,
List(1, 2, 3)))(asMap)
writeBin("tr2", Truck("truck2", 2,
List(7, 8, 9)))(asJson)