Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Scala 2.9.3, bump Algebird #126

Merged
merged 4 commits into from
Jul 18, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: scala
scala:
- 2.10.0
- 2.9.2
- 2.9.3
before_script:
- mysql -u root -e "create database storehaus_test;"
- mysql -u root -e "create user 'storehaususer'@'localhost' identified by 'test1234';"
Expand Down
23 changes: 18 additions & 5 deletions project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ import com.typesafe.tools.mima.plugin.MimaPlugin.mimaDefaultSettings
import com.typesafe.tools.mima.plugin.MimaKeys.previousArtifact

object StorehausBuild extends Build {
def withCross(dep: ModuleID) =
dep cross CrossVersion.binaryMapped {
case "2.9.3" => "2.9.2" // TODO: hack because twitter hasn't built things against 2.9.3
case version if version startsWith "2.10" => "2.10" // TODO: hack because sbt is broken
case x => x
}

val extraSettings =
Project.defaultSettings ++ releaseSettings ++ Boilerplate.settings ++ mimaDefaultSettings

Expand All @@ -28,7 +35,10 @@ object StorehausBuild extends Build {

val sharedSettings = extraSettings ++ ciSettings ++ Seq(
organization := "com.twitter",
crossScalaVersions := Seq("2.9.2", "2.10.0"),

scalaVersion := "2.9.3",

crossScalaVersions := Seq("2.9.3", "2.10.0"),

javacOptions ++= Seq("-source", "1.6", "-target", "1.6"),

Expand Down Expand Up @@ -99,8 +109,8 @@ object StorehausBuild extends Build {
.filterNot(unreleasedModules.contains(_))
.map { s => "com.twitter" % ("storehaus-" + s + "_2.9.2") % "0.3.0" }

val algebirdVersion = "0.1.13"
val bijectionVersion = "0.4.0"
val algebirdVersion = "0.2.0"
val bijectionVersion = "0.5.2"

lazy val storehaus = Project(
id = "storehaus",
Expand Down Expand Up @@ -131,8 +141,11 @@ object StorehausBuild extends Build {
lazy val storehausCache = module("cache")

lazy val storehausCore = module("core").settings(
libraryDependencies += "com.twitter" %% "util-core" % "6.3.7",
libraryDependencies += "com.twitter" %% "bijection-core" % bijectionVersion
libraryDependencies ++= Seq(
withCross("com.twitter" %% "util-core" % "6.3.7"),
"com.twitter" %% "bijection-core" % bijectionVersion,
"com.twitter" %% "bijection-util" % bijectionVersion
)
).dependsOn(storehausCache % "test->test;compile->compile")

lazy val storehausAlgebra = module("algebra").settings(
Expand Down
2 changes: 1 addition & 1 deletion project/Finagle.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ object Finagle {
import sbt._
val LatestVersion = "6.5.1"
def module(name: String, version: String = LatestVersion) =
"com.twitter" %% "finagle-%s".format(name) % version
StorehausBuild.withCross("com.twitter" %% "finagle-%s".format(name) % version)
}
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=0.12.0
sbt.version=0.12.0
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,24 @@ class AlgebraicMutableCache[K, V](cache: MutableCache[K, V]) {
new MutableCache[K, U] {
override def get(k: K) = for {
v <- cache.get(k)
(_, u) <- injection.invert(k, v)
(_, u) <- injection.invert(k, v).toOption
} yield u

override def +=(ku: (K, U)) = { cache += injection(ku); this }

override def hit(k: K) = cache.hit(k).flatMap { injection.invert(k, _) }.map { _._2 }
override def hit(k: K) =
cache.hit(k)
.flatMap(injection.invert(k, _).toOption).map(_._2)

override def evict(k: K) = for {
evictedV <- cache.evict(k)
(_, evictedU) <- injection.invert(k, evictedV)
(_, evictedU) <- injection.invert(k, evictedV).toOption
} yield evictedU

override def empty = new AlgebraicMutableCache(cache.empty).inject(injection)

override def clear = { cache.clear; this }
override def iterator = cache.iterator.flatMap(injection.invert(_))
override def iterator =
cache.iterator.flatMap(injection.invert(_).toOption)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.twitter.storehaus.algebra

import com.twitter.algebird.Semigroup
import com.twitter.bijection.Injection
import scala.util.{ Success, Failure }

/**
* Injection that maps values paired with stale values of T => None
Expand All @@ -27,17 +28,19 @@ import com.twitter.bijection.Injection
* @author Sam Ritchie
*/

case class ExpiredException[K, V](pair: (K, V)) extends RuntimeException(pair.toString)

class TTLInjection[K, T: Ordering: Semigroup, V](delta: T)(clock: () => T) extends Injection[(K, V), (K, (T, V))] {
def apply(pair: (K, V)): (K, (T, V)) = {
val (k, v) = pair
(k, (Semigroup.plus(clock(), delta), v))
}

override def invert(pair: (K, (T, V))): Option[(K, V)] = {
override def invert(pair: (K, (T, V))) = {
val (k, (expiration, v)) = pair
if (Ordering[T].gteq(expiration, clock()))
Some((k, v))
Success(k -> v)
else
None
Failure(ExpiredException(k -> v))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,29 @@
package com.twitter.storehaus

import com.twitter.bijection.Injection
import com.twitter.util.Future
import com.twitter.bijection.Conversion.asMethod
import com.twitter.bijection.twitter_util.UtilBijections._
import com.twitter.util.{ Future, Try }
import scala.util.{ Success, Failure }

/** Use an injection on V2,V1 to convert a store of values V2.
* If the value stored in the underlying store cannot be converted back to V2, then you will get a Future.exception
* containing the string "cannot be converted"
* TODO: we should add a specific exception type here so we can safely filter these cases to Future.None if we so choose.
*/
class ConvertedStore[K1, -K2, V1, V2](store: Store[K1, V1])(kfn: K2 => K1)(implicit inj: Injection[V2, V1])
extends ConvertedReadableStore[K1, K2, V1, V2](store)(kfn)({ v1: V1 =>
inj.invert(v1).map { Future.value(_) }
.getOrElse(Future.exception(new Exception(v1.toString + ": V1 cannot be converted to V2")))
})
with Store[K2, V2] {
extends ConvertedReadableStore[K1, K2, V1, V2](store)(kfn)({ v1: V1 =>
Future.const(inj.invert(v1).as[Try[V2]])
})
with Store[K2, V2] {

override def put(kv: (K2, Option[V2])) = {
val k1 = kfn(kv._1)
val v1 = kv._2.map { inj(_) }
store.put((k1, v1))
}
override def multiPut[K3 <: K2](kvs: Map[K3, Option[V2]]) = {
val mapK1V1 = kvs.map { case (k3, v2) => (kfn(k3), v2.map { inj(_) }) }
val mapK1V1 = kvs.map { case (k3, v2) => (kfn(k3), v2.map(inj(_))) }
val res: Map[K1, Future[Unit]] = store.multiPut(mapK1V1)
kvs.keySet.map { k3 => (k3, res(kfn(k3))) }.toMap
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,28 @@ import org.scalacheck.Gen.choose
import org.scalacheck.Prop._

object StoreProperties extends Properties("Store") {
def baseTest[K: Arbitrary, V: Arbitrary: Equiv](store: Store[K, V])
(put: (Store[K, V], List[(K, Option[V])]) => Unit) =
def baseTest[K: Arbitrary, V: Arbitrary: Equiv](storeIn: => Store[K, V])
(put: (Store[K, V], List[(K, Option[V])]) => Unit) = {
forAll { (examples: List[(K, Option[V])]) =>
lazy val store = storeIn
put(store, examples)
examples.toMap.forall { case (k, optV) =>
Equiv[Option[V]].equiv(Await.result(store.get(k)), optV)
Equiv[Option[V]].equiv(Await.result(store.get(k)), optV)
}
}
}

def putStoreTest[K: Arbitrary, V: Arbitrary: Equiv](store: Store[K, V]) =
def putStoreTest[K: Arbitrary, V: Arbitrary: Equiv](store: => Store[K, V]) =
baseTest(store) { (s, pairs) =>
pairs.foreach { p => Await.result(s.put(p)) }
}

def multiPutStoreTest[K: Arbitrary, V: Arbitrary: Equiv](store: Store[K, V]) =
def multiPutStoreTest[K: Arbitrary, V: Arbitrary: Equiv](store: => Store[K, V]) =
baseTest(store) { (s, pairs) =>
Await.result(FutureOps.mapCollect(s.multiPut(pairs.toMap)))
}

def storeTest[K: Arbitrary, V: Arbitrary: Equiv](store: Store[K, V]) =
def storeTest[K: Arbitrary, V: Arbitrary: Equiv](store: => Store[K, V]) =
putStoreTest(store) && multiPutStoreTest(store)

property("ConcurrentHashMapStore test") =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import com.twitter.storehaus.ConvertedStore
import com.twitter.storehaus.algebra.MergeableStore
import org.jboss.netty.buffer.{ ChannelBuffer, ChannelBuffers }
import org.jboss.netty.util.CharsetUtil
import scala.util.control.Exception.allCatch

import scala.util.Try

/**
* @author Doug Tangren
Expand All @@ -34,7 +35,7 @@ object MemcacheStringStore {
private [memcache] implicit object ByteArrayInjection
extends Injection[Array[Byte],ChannelBuffer] {
def apply(ary: Array[Byte]) = ChannelBuffers.wrappedBuffer(ary)
def invert(buf: ChannelBuffer) = allCatch.opt(buf.array)
def invert(buf: ChannelBuffer) = Try(buf.array)
}
private [memcache] implicit val StringInjection =
Injection.connect[String, Array[Byte], ChannelBuffer]
Expand All @@ -45,7 +46,7 @@ object MemcacheStringStore {
import MemcacheStringStore._

/** A MergeableStore for String values backed by memcache */
class MemcacheStringStore(underlying: MemcacheStore)
class MemcacheStringStore(underlying: MemcacheStore)
extends ConvertedStore[String, String, ChannelBuffer, String](underlying)(identity)
with MergeableStore[String, String] {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ package com.twitter.storehaus.mysql

import java.lang.UnsupportedOperationException

import scala.util.control.Exception.allCatch

import com.twitter.bijection.Injection
import com.twitter.finagle.exp.mysql.{
EmptyValue,
Expand All @@ -36,6 +34,7 @@ import com.twitter.finagle.exp.mysql.{
import org.jboss.netty.buffer.ChannelBuffer
import org.jboss.netty.buffer.ChannelBuffers
import org.jboss.netty.util.CharsetUtil.UTF_8
import scala.util.Try

/** Helper class for mapping finagle-mysql Values to types we care about. */
object ValueMapper {
Expand Down Expand Up @@ -123,7 +122,7 @@ class MySqlValue(val v: Value) {
*/
object MySqlStringInjection extends Injection[MySqlValue, String] {
def apply(a: MySqlValue): String = ValueMapper.toString(a.v).getOrElse("") // should this be null: String instead?
def invert(b: String): Option[MySqlValue] = allCatch.opt(MySqlValue(RawStringValue(b)))
override def invert(b: String) = Try(MySqlValue(RawStringValue(b)))
}

/**
Expand All @@ -133,5 +132,5 @@ object MySqlStringInjection extends Injection[MySqlValue, String] {
*/
object MySqlCbInjection extends Injection[MySqlValue, ChannelBuffer] {
def apply(a: MySqlValue): ChannelBuffer = ValueMapper.toChannelBuffer(a.v).getOrElse(ChannelBuffers.EMPTY_BUFFER)
def invert(b: ChannelBuffer): Option[MySqlValue] = allCatch.opt(MySqlValue(RawStringValue(b.toString(UTF_8))))
override def invert(b: ChannelBuffer) = Try(MySqlValue(RawStringValue(b.toString(UTF_8))))
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ object MySqlStoreProperties extends Properties("MySqlStore")
* we lowercase key's here for normalization */
def stringify(examples: List[(Any, Option[Any])]) =
examples.map { case (k, v) =>
(MySqlStringInjection.invert(k.toString.toLowerCase).get, v.flatMap { d => MySqlStringInjection.invert(d.toString) })
(MySqlStringInjection.invert(k.toString.toLowerCase).get, v.flatMap { d => MySqlStringInjection.invert(d.toString).toOption })
}

def putAndGetStoreTest(store: MySqlStore, pairs: Gen[List[(Any, Option[Any])]] = NonEmpty.Pairing.alphaStrs()) =
Expand Down Expand Up @@ -72,7 +72,7 @@ object MySqlStoreProperties extends Properties("MySqlStore")

def compareValues(k: MySqlValue, expectedOptV: Option[MySqlValue], foundOptV: Option[MySqlValue]) = {
val isMatch = expectedOptV match {
case Some(value) => !foundOptV.isEmpty && foundOptV.get == value
case Some(value) => !foundOptV.isEmpty && foundOptV.get == value
case None => foundOptV.isEmpty
}
if (!isMatch) printErr(k, expectedOptV, foundOptV)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,31 @@ package com.twitter.storehaus.redis

import com.twitter.algebird.Monoid
import com.twitter.bijection.Injection
import com.twitter.bijection.Conversion.asMethod
import com.twitter.finagle.redis.Client
import com.twitter.finagle.redis.util.{ CBToString, StringToChannelBuffer }
import com.twitter.storehaus.ConvertedStore
import com.twitter.storehaus.algebra.MergeableStore
import com.twitter.util.{ Duration, Future }
import org.jboss.netty.buffer.ChannelBuffer
import scala.util.control.Exception.allCatch
import scala.util.Try

/**
*
*
* @author Doug Tangren
*/

object RedisStringStore {
private [redis] implicit object StringInjection
extends Injection[String, ChannelBuffer] {
def apply(a: String): ChannelBuffer = StringToChannelBuffer(a)
def invert(b: ChannelBuffer): Option[String] = allCatch.opt(CBToString(b))
override def invert(b: ChannelBuffer) = Try(CBToString(b))
}

def apply(client: Client, ttl: Option[Duration] = RedisStore.Default.TTL) =
new RedisStringStore(RedisStore(client, ttl))
}

import RedisStringStore._

/**
Expand All @@ -50,9 +52,7 @@ import RedisStringStore._
class RedisStringStore(underlying: RedisStore)
extends ConvertedStore[ChannelBuffer, ChannelBuffer, ChannelBuffer, String](underlying)(identity)
with MergeableStore[ChannelBuffer, String] {
val monoid = implicitly[Monoid[String]]
override val monoid = implicitly[Monoid[String]]
override def merge(kv: (ChannelBuffer, String)): Future[Unit] =
underlying.client.append(kv._1, kv._2).unit
underlying.client.append(kv._1, kv._2.as[ChannelBuffer]).unit
}


Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import com.twitter.util.Await
import org.jboss.netty.buffer.ChannelBuffer
import org.scalacheck.{ Arbitrary, Gen, Properties }
import org.scalacheck.Prop._
import scala.util.control.Exception.allCatch
import scala.util.Try

object RedisStoreProperties extends Properties("RedisStore")
with CloseableCleanup[Store[String, String]]
Expand Down Expand Up @@ -61,7 +61,7 @@ object RedisStoreProperties extends Properties("RedisStore")

implicit def strToCb = new Injection[String, ChannelBuffer] {
def apply(a: String): ChannelBuffer = StringToChannelBuffer(a)
def invert(b: ChannelBuffer): Option[String] = allCatch.opt(CBToString(b))
override def invert(b: ChannelBuffer) = Try(CBToString(b))
}
val closeable =
RedisStore(client).convert(StringToChannelBuffer(_: String))
Expand Down