This library contains Sequentially.scala
which allows running tasks sequentially for the same key and in parallel for different keys
The behavior is somehow similar to what actors propose, however it provides typesafety.
Also, it is easy to write tests using Sequentially.now
to avoid an unnecessary concurrency.
trait Sequentially[-K] {
def apply[KK <: K, T](key: KK)(task: => T): Future[T]
}
This example explains how we can ensure that there are no concurrent updates to var state
type Key = Unit // ok for example
val system = ActorSystem() // yes, we have dependency on akka
val sequentially = Sequentially[Key](system)
var state: Int = 0
// this runs sequentially, like message handling in actors
sequentially(()) {
state = state + 1
}
// you also can expose computation result as Future[T]
val stateBefore: Future[Int] = sequentially(()) {
val stateBefore = state
state = state + 1
stateBefore
}
We usually have more complicated requirements in real life applications,
thus we have implemented more powerful Sequentially-like
structures
trait SequentiallyAsync[-K] extends Sequentially[K] {
def async[KK <: K, T](key: K)(task: => Future[T]): Future[T]
}
trait SequentiallyHandler[-K] extends SequentiallyAsync[K] {
def handler[KK <: K, T](key: KK)(task: => Future[() => Future[T]]): Future[T]
}
And also we have mixed TrieMap
with Sequentially
, results can be found in
- AsyncMap.scala
- SequentialMap.scala
- AsyncHandlerMap.scala
addSbtPlugin("com.evolution" % "sbt-artifactory-plugin" % "0.0.2")
libraryDependencies += "com.evolutiongaming" %% "sequentially" % "1.2.0"