Using rendez vous to synchronous scenarios call

Hi

I’m trying to build following requests simulation case:

  1. 10 req/s
  2. pause(10)
  3. 15 req/s
  4. pause(10)
  5. 20 res/s
    and so on…

To simulate this I’ve used my own rendezVous which is holding next scenarios until previous one is done. It works fine only for the first scenario, next scenarios are started with fully possible req/s as the actors are already waiting. To resolve this I’ve try to use Throttling to limit possible rps, but then the whole rendezVous with pauses doesn’t work :confused: Below is my example implementation:

import java.util.concurrent.atomic.AtomicInteger

import io.gatling.core.Predef._
import io.gatling.core.controller.inject.{InjectionStep, RampInjection}
import io.gatling.core.controller.throttle.{Hold, Reach, Throttling}
import io.gatling.core.structure.{ChainBuilder, PopulatedScenarioBuilder, ScenarioBuilder}
import io.gatling.http.Predef._

class RendezVousTest extends Simulation {

  val rendezVous = new AtomicInteger(0)
  val noOfRequests = 100

  def simulationConfiguration(): List[(InjectionStep, Throttling)] = {
    List(
      (rampUsers(noOfRequests) over 10) -> (reachRps(10) in 10 holdFor 310),
      (rampUsers(noOfRequests) over 6) -> (reachRps(15) in 15 holdFor 456),
      (rampUsers(noOfRequests) over 5) -> (reachRps(20) in 20 holdFor 605),
      (rampUsers(noOfRequests) over 4) -> (reachRps(25) in 25 holdFor 754),
      (rampUsers(noOfRequests) over 3) -> (reachRps(30) in 30 holdFor 903)
    )
  }

  def buildPopulatedScenarios(name: String, action: ChainBuilder): List[PopulatedScenarioBuilder] = {

    def buildScenarioName(name: String, conf: (InjectionStep, Throttling)): String = {
      val stepAsString: String = conf._1 match {
        case s: RampInjection => s"rampUsers ${s.users} over ${s.duration}"
        case any: Any => any.toString
      }
      val throttlerAsString = conf._2.steps.reverse.map({
        case reach: Reach => s"reach ${reach.target} req/sec in ${reach.duration} seconds"
        case hold: Hold => s" hold it for ${hold.durationInSec} seconds "
        case any: Any => any.toString
      }).mkString
      s"$name ($stepAsString; $throttlerAsString)"
    }
    def buildScenario(name: String, action: ChainBuilder, totalUsers: Int): ScenarioBuilder = {
      val from = totalUsers - noOfRequests
      val to = totalUsers

      scenario(name)
        .asLongAs(session => rendezVous.get >= to || rendezVous.get < from) {
          pause(1) //hold this scenario until previous one is finished
        }
        .exec(action)
        .doIf(session => rendezVous.get == to - 1) {
          pause(10) //pause between scenarios
        }
        .exec(session => {
          rendezVous.incrementAndGet
          session
        })
    }

    val usersCount = new AtomicInteger(0)
    val configuration: List[(InjectionStep, Throttling)] = simulationConfiguration()
    configuration.map(conf =>
      buildScenario(buildScenarioName(name, conf), action, usersCount.addAndGet(conf._1.users))
        .inject(conf._1)
        .throttle(conf._2)
    )
  }

  val request =
    "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:hr=\"http://mycompany.com/hr/schemas\"> <SOAP-ENV:Header/> <SOAP-ENV:Body>" +
      "<hr:HolidayRequest>" +
      "   <hr:Holiday>" +
      "      <hr:StartDate>2013-10-20</hr:StartDate>" +
      "      <hr:EndDate>2013-11-22</hr:EndDate>" +
      "   </hr:Holiday>" +
      "   <hr:Employee>" +
      "      <hr:Number>1</hr:Number>" +
      "      <hr:FirstName>John</hr:FirstName>" +
      "      <hr:LastName>Doe</hr:LastName>" +
      "   </hr:Employee>" +
      "</hr:HolidayRequest>" +
      "</SOAP-ENV:Body></SOAP-ENV:Envelope>"

  setUp(buildPopulatedScenarios("Local test",
    exec(exec(http("Send to local")
      .post("http://localhost:8080/services/holidayService/")
      .header("Content-Type", "text/xml")
      .body(StringBody(request))
      .check(status.is(202))
    ))
  )).protocols(http
    .acceptHeader("application/xml")
    .disableCaching)

}