All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
sss.openstar.telemetry.ReportActor.scala Maven / Gradle / Ivy
package sss.openstar.telemetry
import akka.actor.{Actor, ActorContext, ActorLogging, ActorRef, Cancellable, Props}
import sss.ancillary.Serialize._
import sss.openstar.UniqueNodeIdentifier
import sss.openstar.actor.SystemPanic
import sss.openstar.block.BlockChainLedger.NewBlockId
import sss.openstar.block.{BlockClosedEvent, NotSynchronized, Synchronized}
import sss.openstar.chains.LeaderElectionActor.{LeaderFound, LeaderLost}
import sss.openstar.chains.QuorumMonitor.QuorumLost
import sss.openstar.common.block.BlockId
import sss.openstar.common.chains.Quorum
import sss.openstar.common.telemetry._
import sss.openstar.network._
import sss.openstar.telemetry.Client.ClientResponse
import sss.openstar.telemetry.ReportActor.AskForConnections
import scala.concurrent.duration._
import scala.util.Try
object ReportActor {
case object AskForConnections
def props(client: Client, nodeName: String, initialSleepSeconds: Int = 10)
(implicit events: MessageEventBus): Props = Props(classOf[ReportActor], client, nodeName, initialSleepSeconds, events)
def apply(props: Props)(implicit actorSystem: ActorContext): ActorRef = actorSystem.actorOf(props, "ReportActor")
}
class ReportActor(client: Client, nodeName: String, initialSleepSeconds: Int)
(implicit events: MessageEventBus) extends Actor with ActorLogging with SystemPanic {
override def preStart(): Unit = {
super.preStart()
events subscribe classOf[ClientResponse]
events subscribe classOf[NewBlockId]
events subscribe classOf[Connection]
events subscribe classOf[ConnectionLost]
events subscribe classOf[LeaderFound]
events subscribe classOf[LeaderLost]
events subscribe classOf[Quorum]
events subscribe classOf[QuorumLost]
events subscribe classOf[Connections]
events subscribe classOf[Synchronized]
events subscribe classOf[NotSynchronized]
}
private var interval = initialSleepSeconds
import context.dispatcher
/*context.system.scheduler.schedule(
1.seconds, interval.seconds, self, AskForConnections
)*/
private case object ReportTrigger
private var latestBlockId: Option[BlockId] = None
private var currentSync: Option[UniqueNodeIdentifier] = None
private var currentLeader: Option[UniqueNodeIdentifier] = None
private var currentQuorum: Option[Quorum] = None
private var currentConnections: Set[String] = Set.empty
private def resetTrigger(c:Option[Cancellable]): Option[Cancellable] = {
c foreach(_.cancel())
Option(
context.system.scheduler.scheduleOnce(
interval.seconds, self, ReportTrigger
)
)
}
private var cancellable = resetTrigger(None)
override def receive: Receive = {
case AskForConnections =>
events.publish(PublishConnections())
case Connections(conns) =>
val notInCurrent = conns.filterNot(currentConnections.contains)
log.warning(s"Adding $notInCurrent to $conns")
currentConnections ++= conns.toSet
case ClientResponse(rawBs) => Try {
val newReportSleepInterval = rawBs.toArray.extract(IntDeSerialize)
interval = newReportSleepInterval
cancellable = resetTrigger(cancellable)
} recover {
case e => log.warning("Could not decode client telemetry response {}", e)
}
case ReportTrigger =>
val leaderOrSync = if(currentLeader.isDefined) currentLeader else currentSync
val r = Report(nodeName,
interval,
latestBlockId,
leaderOrSync,
currentQuorum,
currentConnections.size,
currentConnections.toSeq
)
client.report(r.toByteString)
cancellable = resetTrigger(cancellable)
case BlockClosedEvent(cId, blockId) =>
latestBlockId = Some(blockId)
case NotSynchronized(_) =>
currentSync = None
case Synchronized(chainId, h, i, upStream) =>
latestBlockId = Some(BlockId(h,i))
currentSync = Some(s"U:$upStream")
case NewBlockId(chId, blockId) =>
latestBlockId = Option(blockId)
case Connection(node) =>
currentConnections += node
case ConnectionLost(node) =>
currentConnections -= node
case newLeader: LeaderFound =>
currentLeader = Option(newLeader.leader)
case leaderLost: LeaderLost =>
currentLeader = None
case ql: QuorumLost =>
currentQuorum = None
case q: Quorum =>
currentQuorum = Some(q)
}
}