All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ru.tinkoff.gatling.transactions.TransactionsActor.scala Maven / Gradle / Ivy

The newest version!
package ru.tinkoff.gatling.transactions

import akka.actor.{Actor, Props, Terminated}
import com.typesafe.scalalogging.LazyLogging
import io.gatling.commons.stats.{KO, OK}
import io.gatling.core.action.Action
import io.gatling.core.session.Session
import io.gatling.core.stats.StatsEngine

import scala.concurrent.duration.Duration

object TransactionsActor {
  def props(statsEngine: StatsEngine): Props =
    Props(new TransactionsActor(statsEngine))

  case class TransactionStarted(name: String, timestamp: Long)
  case class TransactionEnded(name: String, timestamp: Long, session: Session, next: Action)
}

class TransactionsActor(statsEngine: StatsEngine) extends Actor with LazyLogging {

  override def preStart(): Unit = context.setReceiveTimeout(Duration.Undefined)

  override def preRestart(reason: Throwable, message: Option[Any]): Unit =
    logger.error(s"Actor $this crashed on message $message", reason)

  override def unhandled(message: Any): Unit =
    message match {
      case _: Terminated => super.unhandled(message)
      case unknown       => throw new IllegalArgumentException(s"Actor $this doesn't support message $unknown")
    }

  private def crash(prefix: String, errorMsg: String, session: Session, next: Action): Unit = {
    statsEngine.logCrash(session.scenario, session.groups, prefix, errorMsg)
    next ! session.markAsFailed
  }

  private def executeNext(name: String, startTimestamp: Long, stopTimestamp: Long, session: Session, next: Action): Unit = {
    statsEngine.logResponse(
      session.scenario,
      session.groups,
      name,
      startTimestamp,
      stopTimestamp,
      if (session.isFailed) KO else OK,
      None,
      if (session.isFailed) Some(s"transaction '$name' failed") else None,
    )
    next ! session.logGroupRequestTimings(startTimestamp, stopTimestamp)
  }

  def onTransaction(transactionsStack: List[TransactionsActor.TransactionStarted]): Receive = {
    case t: TransactionsActor.TransactionStarted                            =>
      context.become(onTransaction(t :: transactionsStack))
    case TransactionsActor.TransactionEnded(name, timestamp, session, next) =>
      transactionsStack match {
        case Nil =>
          crash(s"Transaction '$name' close error", s"transaction '$name' wasn't started", session, next)

        case started :: newStack =>
          if (started.timestamp > timestamp) {
            crash(s"Transaction '$name' illegal state", s"transaction not be able end before they started", session, next)
          } else if (started.name == name) {
            executeNext(name, started.timestamp, timestamp, session, next)
          } else {
            crash(s"Transaction '$name' close error", s"has unclosed transaction ${started.name}", session, next)
          }
          context.become(onTransaction(newStack))
      }
  }

  override def receive: Receive = onTransaction(List.empty)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy