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.test.MultiTx.scala Maven / Gradle / Ivy
package sss.openstar.test
import akka.actor.Status.{Failure => FutureFailure}
import akka.actor.{Actor, ActorContext, ActorLogging, ActorRef, ActorSystem, Cancellable, Props, ReceiveTimeout}
import akka.pattern.pipe
import sss.db
import sss.openstar.StartupHooks.HookDone
import sss.openstar.chains.TxWriterActor._
import sss.openstar.counterledger.{CounterLedger, CounterLedgerTx, FailOnTheseNodes, IncrementFailure}
import sss.openstar.ledger.{LedgerId, LedgerItem, SignedTxEntry}
import sss.openstar.network.MessageEventBus
import sss.openstar.test.MultiIdentityTestTransactionSender.FireTxs
import sss.openstar.tools.SendTxSupport.SendTx
import scala.concurrent.duration._
object MultiTx {
case object Printout
def apply(counterLedger: CounterLedger,
counterLedgerId: LedgerId,
maxInProgress: Int)(implicit context: ActorContext,
sendTx: SendTx,
events: MessageEventBus,
runContext: db.SyncRunContext): ActorRef = {
context.actorOf(Props(new MultiTx(counterLedger, counterLedgerId, maxInProgress)), "MultiTx")
}
}
class MultiTx(counterLedger: CounterLedger,
counterLedgerId: LedgerId,
maxInProgress: Int)(implicit actorContext: ActorContext,
sendTx: SendTx,
events: MessageEventBus,
runContext: db.SyncRunContext)
extends Actor with ActorLogging {
override def preStart(): Unit = {
super.preStart()
events.subscribe(HookDone.getClass)
}
private def createLedgerItem(cmd: CounterLedgerTx) =
LedgerItem(counterLedgerId, cmd.txId, SignedTxEntry(cmd.toBytes).toBytes)
private def createIncrementFailure = createLedgerItem(IncrementFailure())
private def createFailOnNodes = {
createLedgerItem(FailOnTheseNodes(Seq.empty))
}
import actorContext.dispatcher
actorContext.setReceiveTimeout(120.seconds)
val printoutTimeout = 60.seconds
val as = actorContext.system
private var inProgress = 0
private var totalTxsProcessed: Int = 0
private var rejectedTxs: Int = 0
private var schedFire: Option[Cancellable] = None
private def scheduleFireTxs(delayInSeconds: Int): Unit = schedFire = schedFire match {
case None => Option(as.scheduler.scheduleOnce(delayInSeconds.seconds, self, FireTxs))
case x if inProgress <= 0 =>
x.map(_.cancel())
Option(as.scheduler.scheduleOnce(delayInSeconds.seconds, self, FireTxs))
case x => x
}
override def receive: Receive = {
case HookDone =>
log.info("Starting!")
scheduleFireTxs(1)
as.scheduler.scheduleOnce(printoutTimeout, self, Printout)
case FutureFailure(e) =>
log.debug(s"Failed, retry, $e")
inProgress -= 1
scheduleFireTxs(2)
case r: InternalNack =>
log.warning(s"Rejected tx $r")
rejectedTxs += 1
inProgress -= 1
scheduleFireTxs(2)
case r: InternalTempNack =>
log.debug("TEMP NACK")
inProgress -= 1
scheduleFireTxs(2)
case com: InternalCommit =>
log.debug(s"Got commit: $com, going again")
inProgress -= 1
totalTxsProcessed += 1
scheduleFireTxs(0)
case ReceiveTimeout =>
val counter = counterLedger.successCounter().runSyncAndGet
val failures = counterLedger.failureCounter().runSyncAndGet
log.info(s"totalProcessed = $totalTxsProcessed counter = $counter failures = $failures")
context.setReceiveTimeout(Duration.Inf)
case FireTxs if inProgress < maxInProgress =>
log.debug("FireTxs!")
(0 until (maxInProgress - inProgress)) foreach { _ =>
inProgress += 1
sendTx(createFailOnNodes).whenAvailableLocally.map(_.commitTxResult.internalCommit) pipeTo self
}
case FireTxs =>
log.debug("FireTxs ")
if (inProgress % 10 == 0) log.debug(s"$inProgress in progress, wait x seconds.... (total ${totalTxsProcessed})")
scheduleFireTxs(10)
case Printout =>
log.info(s"Printout total=$totalTxsProcessed and rejected=$rejectedTxs")
as.scheduler.scheduleOnce(printoutTimeout, self, Printout)
}
}