@@ -9,15 +9,16 @@ import ch.epfl.pop.json.MessageDataProtocol.GreetLaoFormat
9
9
import ch .epfl .pop .model .network .method .message .Message
10
10
import ch .epfl .pop .model .network .method .message .data .lao .GreetLao
11
11
import ch .epfl .pop .model .network .method .message .data .{ActionType , ObjectType }
12
+ import ch .epfl .pop .model .objects .*
12
13
import ch .epfl .pop .model .objects .Channel .{LAO_DATA_LOCATION , ROOT_CHANNEL_PREFIX }
13
- import ch .epfl .pop .model .objects ._
14
14
import ch .epfl .pop .pubsub .graph .AnswerGenerator .timout
15
15
import ch .epfl .pop .pubsub .graph .{ErrorCodes , JsonString }
16
16
import ch .epfl .pop .pubsub .{MessageRegistry , PubSubMediator , PublishSubscribe }
17
- import ch .epfl .pop .storage .DbActor ._
17
+ import ch .epfl .pop .storage .DbActor .*
18
18
import com .google .crypto .tink .subtle .Ed25519Sign
19
19
20
20
import java .util .concurrent .TimeUnit
21
+ import scala .collection .immutable .HashMap
21
22
import scala .concurrent .Await
22
23
import scala .concurrent .duration .{Duration , FiniteDuration }
23
24
import scala .util .{Failure , Success , Try }
@@ -130,7 +131,7 @@ final case class DbActor(
130
131
131
132
@ throws[DbActorNAckException ]
132
133
private def readElectionData (laoId : Hash , electionId : Hash ): ElectionData = {
133
- Try (storage.read(storage.DATA_KEY + s " ${ ROOT_CHANNEL_PREFIX } ${laoId.toString}/private/ ${electionId.toString}" )) match {
134
+ Try (storage.read(storage.DATA_KEY + s " $ROOT_CHANNEL_PREFIX${laoId.toString}/private/ ${electionId.toString}" )) match {
134
135
case Success (Some (json)) => ElectionData .buildFromJson(json)
135
136
case Success (None ) => throw DbActorNAckException (ErrorCodes .SERVER_ERROR .id, s " ElectionData for election $electionId not in the database " )
136
137
case Failure (ex) => throw ex
@@ -243,7 +244,7 @@ final case class DbActor(
243
244
244
245
@ throws[DbActorNAckException ]
245
246
private def createElectionData (laoId : Hash , electionId : Hash , keyPair : KeyPair ): Unit = {
246
- val channel = Channel (s " ${ ROOT_CHANNEL_PREFIX } ${laoId.toString}/private/ ${electionId.toString}" )
247
+ val channel = Channel (s " $ROOT_CHANNEL_PREFIX${laoId.toString}/private/ ${electionId.toString}" )
247
248
if (! checkChannelExistence(channel)) {
248
249
val pair = (storage.DATA_KEY + channel.toString) -> ElectionData (electionId, keyPair).toJsonString
249
250
storage.write(pair)
@@ -299,7 +300,7 @@ final case class DbActor(
299
300
@ throws[DbActorNAckException ]
300
301
private def generateLaoDataKey (channel : Channel ): String = {
301
302
channel.decodeChannelLaoId match {
302
- case Some (data) => storage.DATA_KEY + s " ${Channel .ROOT_CHANNEL_PREFIX }$data${ LAO_DATA_LOCATION } "
303
+ case Some (data) => storage.DATA_KEY + s " ${Channel .ROOT_CHANNEL_PREFIX }$data$LAO_DATA_LOCATION"
303
304
case None =>
304
305
log.error(s " Actor $self (db) encountered a problem while decoding LAO channel from ' $channel' " )
305
306
throw DbActorNAckException (ErrorCodes .SERVER_ERROR .id, s " Could not extract the LAO id for channel $channel" )
@@ -308,7 +309,7 @@ final case class DbActor(
308
309
309
310
// generates the key of the RollCallData to store in the database
310
311
private def generateRollCallDataKey (laoId : Hash ): String = {
311
- storage.DATA_KEY + s " ${ ROOT_CHANNEL_PREFIX } ${laoId.toString}/rollcall "
312
+ storage.DATA_KEY + s " $ROOT_CHANNEL_PREFIX${laoId.toString}/rollcall "
312
313
}
313
314
314
315
@ throws[DbActorNAckException ]
@@ -369,6 +370,20 @@ final case class DbActor(
369
370
(publicKey, privateKey)
370
371
}
371
372
373
+ @ throws[DbActorNAckException ]
374
+ private def generateHeartbeat (): HashMap [Channel , Set [Hash ]] = {
375
+ val setOfChannels = getAllChannels
376
+ if (setOfChannels.isEmpty) return HashMap ()
377
+ val heartbeatMap : HashMap [Channel , Set [Hash ]] = setOfChannels.foldLeft(HashMap .empty[Channel , Set [Hash ]]) {
378
+ (acc, channel) =>
379
+ readChannelData(channel).messages.toSet match {
380
+ case setOfIds if setOfIds.nonEmpty => acc + (channel -> setOfIds)
381
+ case _ => acc
382
+ }
383
+ }
384
+ heartbeatMap
385
+ }
386
+
372
387
override def receive : Receive = LoggingReceive {
373
388
case Write (channel, message) =>
374
389
log.info(s " Actor $self (db) received a WRITE request on channel ' $channel' " )
@@ -543,6 +558,13 @@ final case class DbActor(
543
558
case failure => sender() ! failure.recover(Status .Failure (_))
544
559
}
545
560
561
+ case GenerateHeartbeat () =>
562
+ log.info(s " Actor $self (db) received a GenerateHeartbeat request " )
563
+ Try (generateHeartbeat()) match {
564
+ case Success (heartbeat) => sender() ! DbActorGenerateHeartbeatAck (heartbeat)
565
+ case failure => sender() ! failure.recover(Status .Failure (_))
566
+ }
567
+
546
568
case m =>
547
569
log.info(s " Actor $self (db) received an unknown message " )
548
570
sender() ! Status .Failure (DbActorNAckException (ErrorCodes .INVALID_ACTION .id, s " database actor received a message ' $m' that it could not recognize " ))
@@ -758,6 +780,9 @@ object DbActor {
758
780
*/
759
781
final case class ReadServerPrivateKey () extends Event
760
782
783
+ /** Request to generate a local heartbeat */
784
+ final case class GenerateHeartbeat () extends Event
785
+
761
786
// DbActor DbActorMessage correspond to messages the actor may emit
762
787
sealed trait DbActorMessage
763
788
@@ -832,6 +857,13 @@ object DbActor {
832
857
*/
833
858
final case class DbActorReadServerPrivateKeyAck (privateKey : PrivateKey ) extends DbActorMessage
834
859
860
+ /** Response for a [[GenerateHeartbeat ]] db request Receiving [[DbActorGenerateHeartbeatAck ]] works as an acknowledgement that the request was successful
861
+ *
862
+ * @param heartbeatMap
863
+ * requested heartbeat as a map from the channels to message ids
864
+ */
865
+ final case class DbActorGenerateHeartbeatAck (heartbeatMap : HashMap [Channel , Set [Hash ]]) extends DbActorMessage
866
+
835
867
/** Response for a general db actor ACK
836
868
*/
837
869
final case class DbActorAck () extends DbActorMessage
0 commit comments