Created
August 4, 2011 13:47
-
-
Save rktoomey/1125182 to your computer and use it in GitHub Desktop.
Binary "when necessary" type hinting with Salat
This file contains 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
package com.novus.salat.test | |
import com.novus.salat.util.encoding.TypeHintEncoding | |
import com.novus.salat.{ TypeHintFrequency, BinaryTypeHintStrategy, Context } | |
package object when_necessary_binary_type_hint_encoding { | |
implicit val ctx = new Context { | |
val name = Some("WhenNecessary-BinaryTypeHint") | |
override val typeHintStrategy = BinaryTypeHintStrategy(when = TypeHintFrequency.WhenNecessary, | |
typeHint = "t", | |
encoding = TypeHintEncoding.UsAsciiEncoding) | |
} | |
} | |
package object model { | |
@Salat | |
trait SomeTrait extends Product | |
case class SomeTraitImpl1(x: String) extends SomeTrait | |
case class SomeTraitImpl2(y: Int) extends SomeTrait | |
} |
This file contains 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
salat-core:master:0.0.8-SNAPSHOT> test:console | |
[info] Starting scala interpreter... | |
[info] | |
Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_26). | |
Type in expressions to have them evaluated. | |
Type :help for more information. | |
scala> import com.novus.salat._ | |
import com.novus.salat._ | |
scala> import com.novus.salat.test.when_necessary_binary_type_hint_encoding._ | |
import com.novus.salat.test.when_necessary_binary_type_hint_encoding._ | |
scala> import com.novus.salat.test.model._ | |
import com.novus.salat.test.model._ | |
scala> val x: SomeTrait = SomeTraitImpl2(y = 3) | |
x: com.novus.salat.test.model.SomeTrait = SomeTraitImpl2(3) | |
scala> val dbo = grater[SomeTrait].asDBObject(x) | |
2 [run-main] INFO com.novus.salat.test.when_necessary_binary_type_hint_encoding.package$$anon$7 - accept: ctx='WhenNecessary-BinaryTypeHint' accepted grater[com.novus.salat.test.model.SomeTrait] | |
8 [run-main] INFO com.novus.salat.test.when_necessary_binary_type_hint_encoding.package$$anon$7 - accept: ctx='WhenNecessary-BinaryTypeHint' accepted grater[com.novus.salat.test.model.SomeTraitImpl2] | |
285 [run-main] INFO com.novus.salat.BinaryTypeHintStrategy - toTypeHint: put 'com.novus.salat.test.model.SomeTraitImpl2' ---> 184477527298863911571054983976302194159472974158232255170769888682740810047 | |
286 [run-main] INFO com.novus.salat.BinaryTypeHintStrategy - fromTypeHint: put 184477527298863911571054983976302194159472974158232255170769888682740810047 ---> 'com.novus.salat.test.model.SomeTraitImpl2' | |
dbo: com.mongodb.casbah.Imports.DBObject = { "t" : <Binary Data> , "y" : 3} | |
scala> import com.mongodb.casbah.Imports._ | |
import com.mongodb.casbah.Imports._ | |
scala> val dbo:MongoDBObject = grater[SomeTrait].asDBObject(x) | |
dbo: com.mongodb.casbah.Imports.MongoDBObject = Map((t,[B@a7046e7), (y,3)) | |
scala> val x_* = grater[SomeTrait].asObject(dbo) | |
x_*: com.novus.salat.test.model.SomeTrait = SomeTraitImpl2(3) | |
scala> x == x_* | |
res0: Boolean = true |
This file contains 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
Binary type hint encoding uses a charset to create a base N representation for encoding and decoding | |
String <-> BigInt (which is saved as a ByteArray). Requires latest 0.0.8-SNAPSHOT of salat-core. | |
Novus is currently using binary type hint encoding in our staging environment. | |
See com.novus.salat.util.encoding.TypeHintEncoding and com.novus.salat.BinaryTypeHintStrategy for | |
details. | |
Details include: | |
* binary type hint encoding to customized charset | |
** Array[Byte] <-> BigInt <-> String | |
* the conversion is expensive relative to just using strings, but it is memoized in both directions | |
(that's what the log statements with the BigInts in the test:console session above are about) | |
* backwards compatible with String type hints - on receiving a String, the decoder just passes it | |
through | |
* if you use com.mongodb.util.JSON for parsing JSON, it's going to fall down because it handles | |
Binary/byte[] as the string "<Binary Data>" - we forked and patched the mongo-java-driver locally and I | |
will submit a pull request to 10gen once I have time to write a unit test for it | |
When using US ASCII for Java identifiers, the binary representation is about 20% more efficient than the | |
String. The full list of every unicode character that is a legal Java identifier is around 2X the size | |
of the string (we supply this charset just in case you want to play around with it), so you will need | |
to fine tune your charset if you use non-US ASCII characters in your package or class names. | |
CAVEAT: CASE OBJECTS | |
Right now, if you choose a binary type hinting strategy, type hints for everything EXCEPT case objects | |
will be encoded and persisted to MongoDB as byte arrays. | |
Since we have queries around our case objects, we prefer to have case object type hints encoded as | |
Strings. (@patriknw, we will be making this configurable very soon, I promise... :) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment