bitcoin-atm
bitcoin atm for pyc inc.
git clone https://9o.is/git/bitcoin-atm.git
Minion.scala
(2565B)
1 package inc.pyc.chimera
2 package minions
3
4 import akka.actor._
5 import SupervisorStrategy._
6 import akka.util.Timeout
7 import concurrent.duration._
8
9 /**
10 * Minion does all the workload for Overlord. In case disaster
11 * occurs, the minion dies.
12 */
13 trait Minion {
14 this: Actor with ActorLogging =>
15
16 import context.dispatcher
17
18 // Those damn minions better hurry
19 implicit val timeout = Timeout(7 seconds)
20
21 /**
22 * Tasks that can be done by the minion.
23 */
24 val tasks: Receive
25
26 /**
27 * Minion kills itself
28 */
29 def die = context stop self
30
31 /**
32 * Minion runs its task and kills itself afterwards.
33 */
34 def runTask (func: => Unit) {
35 func
36 die
37 }
38
39 /**
40 * Minion runs its task and kills itself after timer ends or
41 * something else kills it.
42 */
43 def runTask_Wait (duration: FiniteDuration) (func: => Unit) {
44 func
45 context.system.scheduler.scheduleOnce(duration)(die)
46 }
47
48 /**
49 * Only Overlord creates and runs minions.
50 */
51 def overlord = context parent
52
53
54 def receive: Receive = tasks orElse {
55 case term: Terminated =>
56 log error "Minion could not complete its task"
57 context stop self
58 }
59 }
60
61 /**
62 * Minion that launches a worker that can do the
63 * job.
64 */
65 trait MinionWorker {
66 this: Actor with Minion =>
67
68 /**
69 * Props for worker actor
70 */
71 def props: Props
72
73 /**
74 * Name for worker actor
75 */
76 def name: String
77
78 /**
79 * Creates a worker and kills it after it's
80 * done doing its job.
81 */
82 def workout (func: ActorRef => Unit) {
83 val worker = context.actorOf(props, name)
84 context watch worker
85 func(worker)
86 kill(worker)
87 }
88
89 /**
90 * Creates a worker and kills it after it's
91 * done doing its job. Returns a result.
92 */
93 def workout_[T] (func: ActorRef => T): T = {
94 val worker = context.actorOf(props, name)
95 context watch worker
96 val result = func(worker)
97 kill(worker)
98 result
99 }
100
101 /**
102 * Kills the worker actor and becomes ready to die.
103 * If the minion never hears from the worker, it kills itself.
104 * @param worker worker actor
105 */
106 def kill(worker: ActorRef) = {
107 context become dying(worker)
108 worker ! PoisonPill
109 }
110
111 /**
112 * Minion is dying.
113 * Once worker is dead, minion kills itself.
114 */
115 def dying(worker: ActorRef): Receive = {
116 case Terminated(`worker`) => die
117 case _ =>
118 }
119 }