Skip to content

Instantly share code, notes, and snippets.

@milenkovicm
Forked from derekwyatt/FutureShutdown.scala
Created January 23, 2017 10:44
Show Gist options
  • Save milenkovicm/f077db3efd88a007a85fd60858cc9fad to your computer and use it in GitHub Desktop.
Save milenkovicm/f077db3efd88a007a85fd60858cc9fad to your computer and use it in GitHub Desktop.
Shutdown pattern
// Spawn your futures
val fs = (1 to 100).map { i =>
Future { Thread.sleep(i); i }
}
// Wrap all of the work up into a single
// Future
val f = Future.sequence(fs)
// Wait on it forever - i.e. until it's done
Await.result(f, Duration.Inf)
// Shut down
system.shutdown()
class ProductionReaper extends Reaper {
// Shutdown
def allSoulsReaped(): Unit = context.system.shutdown()
}
import akka.actor.{Actor, ActorRef, Terminated}
import scala.collection.mutable.ArrayBuffer
object Reaper {
// Used by others to register an Actor for watching
case class WatchMe(ref: ActorRef)
}
abstract class Reaper extends Actor {
import Reaper._
// Keep track of what we're watching
val watched = ArrayBuffer.empty[ActorRef]
// Derivations need to implement this method. It's the
// hook that's called when everything's dead
def allSoulsReaped(): Unit
// Watch and check for termination
final def receive = {
case WatchMe(ref) =>
context.watch(ref)
watched += ref
case Terminated(ref) =>
watched -= ref
if (watched.isEmpty) allSoulsReaped()
}
}
import akka.actor.{ActorSystem, Props, ActorRef}
import akka.testkit.{TestKit, ImplicitSender, TestProbe}
import org.scalatest.{WordSpec, BeforeAndAfterAll}
import org.scalatest.matchers.MustMatchers
// Our test reaper. Sends the snooper a message when all
// the souls have been reaped
class TestReaper(snooper: ActorRef) extends Reaper {
def allSoulsReaped(): Unit = snooper ! "Dead"
}
class ReaperSpec extends TestKit(ActorSystem("ReaperSpec"))
with ImplicitSender
with WordSpec
with BeforeAndAfterAll
with MustMatchers {
import Reaper._
override def afterAll() {
system.shutdown()
}
"Reaper" should {
"work" in {
// Set up some dummy Actors
val a = TestProbe()
val b = TestProbe()
val c = TestProbe()
val d = TestProbe()
// Build our reaper
val reaper = system.actorOf(Props(new TestReaper(testActor)))
// Watch a couple
reaper ! WatchMe(a.ref)
reaper ! WatchMe(d.ref)
// Stop them
system.stop(a.ref)
system.stop(d.ref)
// Make sure we've been called
expectMsg("Dead")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment