I have a scenario I'm trying to simulate and I'm not sure about the best / most idiomatic way to go about it.
The app I'm working with generates some very large reports that take a long time to execute. For our primary web client, we start the report generation, then poll for something like {"result":"COMPLETED"}
in the response. But the client will only poll for so long - after 5 minutes without seeing the COMPLETED
response, it gives up and displays an error message to the user. What I would like to be able to do is capture this as a fail in the scenario.
I've currently got it implemented something like this...
exitBlockOnFail {
group("report polling") {
exec(_.set("completed", false))
.doWhileDuring(session => !session("completed").as[Boolean], timeout) {
exec(
http("polling action")
...
.check(jsonPath("$.result").transform(result => "COMPLETED".equals(result)).saveAs("completed")
)
}
// if we got here and didn't succeed then we timed out. This will mark the group as failed.
// failures on the polling action trigger an exit from the block
.doIf(session => !session("completed").as[Boolean])
{
exec(session => {
//logging a message to the console as there's no way to get this into the simulation.log
println(s"**** $description failed took more than: ${timeout.toString} (user: ${session("user").as[String]}****")
session.markAsFailed
})
}
}
}
This shows up in the gatling reports as a failure on the group, but there's no error message as the fail is not associated with a request. This makes deciphering the report difficult as some of the group fails might also be caused by failures on the polling request.
The other approach I've just started playing with is to use a check.transform
on the polling request that uses a timestamp in the session set at the start of the group execution to determine if the timeout has been exceeded. This means that the failure is now on a request and gets a meaningful message in the reports
group("report polling") {
exec(_.set("start", DateTime.now()))
.doWhileDuring(session => !session("result").as[String].equals("5"), timeout) {
exec( http("polling action")
...
.check(
responseTimeInMillis.transform((responseTime, session) => DateTime.now.getMillis - session("start")
.as[DateTime].getMillis).lte(timeout).name("Report generation timed out")
))
}
}}
But this feels messy - the polling action has not actually failed and logic around group behaviour has leaked into the request definition.
Ideally, I'd like to have a .check
method on the group where I could just assert that the group duration was less than the timeout, but I don't think this is possible.