Created
May 13, 2014 08:16
-
-
Save ornicar/0d9354abbe364fc3ae01 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
/** | |
* Ensure asynchronous functions are run sequentially. | |
* This implementation is for Future[Unit], | |
* so the work is sent in fire-and-forget style, | |
* and we don't care about the function result. | |
* | |
* Usage: | |
* val sequencer = new Sequencer | |
* sequencer ! Sequencer.work(updateDatabaseAsynchronously) | |
* sequencer ! Sequencer.work(moreUpdate) | |
* | |
* the `moreUpdate` function will be called when `updateDatabaseAsynchronously` completes. | |
*/ | |
final class Sequencer extends Actor { | |
private def idle: Receive = { | |
case msg => | |
context become busy | |
processThenDone(msg) | |
} | |
private def busy: Receive = { | |
case Done => dequeue match { | |
case None => context become idle | |
case Some(work) => processThenDone(work) | |
} | |
case msg => queue enqueue msg | |
} | |
def receive = idle | |
private val queue = collection.mutable.Queue[Any]() | |
private def dequeue: Option[Any] = Try(queue.dequeue).toOption | |
private case object Done | |
private def processThenDone(work: Any) { | |
work match { | |
case Sequencer.Work(run) => run() andThenAnyway { self ! Done } | |
case x => play.api.Logger("Sequencer").warn(s"Unsupported message $x") | |
} | |
} | |
} | |
object Sequencer { | |
case class Work(run: () => Funit) | |
def work(run: => Funit): Work = Work(() => run) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment