@@ -40,6 +40,7 @@ case object Active extends KeepAliveServiceState
40
40
sealed trait KeepAliveServiceData
41
41
case object NoData extends KeepAliveServiceData
42
42
case class Lease (id : Long , ttl : Long ) extends KeepAliveServiceData
43
+ case class ActiveStates (worker : Cancellable , lease : Lease ) extends KeepAliveServiceData
43
44
44
45
// Events received by the actor
45
46
case object RegrantLease
@@ -48,7 +49,7 @@ case object GrantLease
48
49
49
50
// Events internally used
50
51
case class SetLease (lease : Lease )
51
- case object SetWatcher
52
+ case class SetWatcher ( worker : Cancellable )
52
53
53
54
class LeaseKeepAliveService (etcdClient : EtcdClient , instanceId : InstanceId , watcherService : ActorRef )(
54
55
implicit logging : Logging ,
@@ -59,15 +60,14 @@ class LeaseKeepAliveService(etcdClient: EtcdClient, instanceId: InstanceId, watc
59
60
implicit val ec : ExecutionContextExecutor = context.dispatcher
60
61
61
62
private val leaseTimeout = loadConfigOrThrow[Int ](ConfigKeys .etcdLeaseTimeout).seconds
62
- private var worker : Option [Cancellable ] = None
63
63
private val key = instanceLease(instanceId)
64
64
private val watcherName = " lease-service"
65
65
66
66
self ! GrantLease
67
67
startWith(Ready , NoData )
68
68
69
69
when(Ready ) {
70
- case Event (GrantLease , _ ) =>
70
+ case Event (GrantLease , NoData ) =>
71
71
etcdClient
72
72
.grant(leaseTimeout.toSeconds)
73
73
.map { res =>
@@ -76,14 +76,14 @@ class LeaseKeepAliveService(etcdClient: EtcdClient, instanceId: InstanceId, watc
76
76
.pipeTo(self)
77
77
stay
78
78
79
- case Event (SetLease (lease), _ ) =>
79
+ case Event (SetLease (lease), NoData ) =>
80
80
startKeepAliveService(lease)
81
81
.pipeTo(self)
82
82
logging.info(this , s " Granted a new lease $lease" )
83
83
stay using lease
84
84
85
- case Event (SetWatcher , lease : Lease ) =>
86
- goto(Active ) using lease
85
+ case Event (SetWatcher (w), l : Lease ) =>
86
+ goto(Active ) using ActiveStates (w, l)
87
87
88
88
case Event (t : FailureMessage , _) =>
89
89
logging.warn(this , s " Failed to grant new lease caused by: $t" )
@@ -94,15 +94,15 @@ class LeaseKeepAliveService(etcdClient: EtcdClient, instanceId: InstanceId, watc
94
94
}
95
95
96
96
when(Active ) {
97
- case Event (WatchEndpointRemoved (`key`, `key`, _, false ), lease : Lease ) =>
97
+ case Event (WatchEndpointRemoved (`key`, `key`, _, false ), ActiveStates (worker, lease) ) =>
98
98
logging.info(this , s " endpoint ie removed so recreate a lease " )
99
- recreateLease(lease)
99
+ recreateLease(worker, lease)
100
100
101
- case Event (RegrantLease , lease : Lease ) =>
101
+ case Event (RegrantLease , ActiveStates (worker, lease) ) =>
102
102
logging.info(this , s " ReGrant a lease, old lease: ${lease}" )
103
- recreateLease(lease)
103
+ recreateLease(worker, lease)
104
104
105
- case Event (GetLease , lease : Lease ) =>
105
+ case Event (GetLease , ActiveStates (_, lease) ) =>
106
106
logging.info(this , s " send the lease( ${lease}) to ${sender()}" )
107
107
sender() ! lease
108
108
stay()
@@ -112,18 +112,17 @@ class LeaseKeepAliveService(etcdClient: EtcdClient, instanceId: InstanceId, watc
112
112
113
113
initialize()
114
114
115
- private def startKeepAliveService (lease : Lease ): Future [SetWatcher . type ] = {
116
- worker = Some {
115
+ private def startKeepAliveService (lease : Lease ): Future [SetWatcher ] = {
116
+ val worker =
117
117
actorSystem.scheduler.schedule(initialDelay = 0 .second, interval = 500 .milliseconds)(keepAliveOnce(lease))
118
- }
119
118
120
119
/**
121
120
* To verify that lease has been deleted since timeout,
122
121
* create a key using lease, watch the key, and receive an event for deletion.
123
122
*/
124
123
etcdClient.put(key, s " ${lease.id}" , lease.id).map { _ =>
125
124
watcherService ! WatchEndpoint (key, s " ${lease.id}" , false , watcherName, Set (DeleteEvent ))
126
- SetWatcher
125
+ SetWatcher (worker)
127
126
}
128
127
}
129
128
@@ -139,14 +138,14 @@ class LeaseKeepAliveService(etcdClient: EtcdClient, instanceId: InstanceId, watc
139
138
}
140
139
}
141
140
142
- private def recreateLease (lease : Lease ) = {
141
+ private def recreateLease (worker : Cancellable , lease : Lease ) = {
143
142
logging.info(this , s " recreate a lease, old lease: $lease" )
144
- worker.foreach(_. cancel() ) // stop scheduler
143
+ worker.cancel() // stop scheduler
145
144
watcherService ! UnwatchEndpoint (key, false , watcherName) // stop watcher
146
145
etcdClient
147
146
.revoke(lease.id) // delete lease
148
147
.onComplete(_ => self ! GrantLease ) // create lease
149
- goto(Ready )
148
+ goto(Ready ) using NoData
150
149
}
151
150
152
151
// Unstash all messages stashed while in intermediate state
@@ -162,7 +161,10 @@ class LeaseKeepAliveService(etcdClient: EtcdClient, instanceId: InstanceId, watc
162
161
}
163
162
164
163
override def postStop (): Unit = {
165
- worker.foreach(_.cancel()) // stop scheduler if that exist
164
+ stateData match {
165
+ case ActiveStates (w, _) => w.cancel() // stop scheduler if that exist
166
+ case _ => // do nothing
167
+ }
166
168
watcherService ! UnwatchEndpoint (key, false , watcherName)
167
169
}
168
170
}
0 commit comments