Code issue ....strange behavior.

Hi gatling experts.
my application waiting for opened connection from BIG IP (F5).

I want to check connection by ping every 10 seconds, but with timeout of 10 minutes.

But this code just don’t works as designed .
It works only when I comment red signed rows , but if something goes wrong with connection it stuck in loop without timeout handling.
I need an idea to handle timeout or to know what wrong with this code.

Thanks for advance.

Greg.

/** Check if connected mode is ready (use Ping) */
val checkConnectedModeStatus = group(“Check Connected Mode”) {
asLongAs(session => session(“connectedModeStatus”).as[String].contains(“None”), exitASAP = false) {
exec(getConnectingModeIndicator)
**.doIfOrElse(session => {System.currentTimeMillis().toLong - session(“flowStartTime”).as[Long] > 60000.toLong}) { //’**flowStartTime’ contains System.currentTimeMillis() of first ping
exec(session => session.markAsFailed).exitHereIfFailed
} {
pause(10 seconds)
}

}
}
.
.
.

val getConnectingModeIndicator = http(“Check Connecting Mode is ready”)
.get(""“http://”"" + domain + “”"/sandbox/${testName}/${username}/in/flow/ping""")
.check(regex(""“sandbox.${testName}.${username}.in.flow”"").optional.saveAs(“connectedModeStatus”)) //'connectedModeStatus’
in the beginning of scenario initialized to “None”


.check(status.in(Seq(200, 0))).silent

Do you set an initial value for checkConnectedModeStatus?

Otherwise, you’re checking it in the asLongAs loop condition while it’s only being set later in exec(getConnectingModeIndicator).
As you use a “as” instead of a “validate”, the condition evaluation will crash with an exception.

Hi Stephane.

  1. I initialized checkConnectedModeStatus to “None” at start of simulation.

Do you suggest to use “validate” instead of “as”?

What about flowStartTime? Is it properly initialized?
Have you tried logging inside the condition functions?

validate is more functional, and will give you accurate messages and failures that will be handled gracefully, instead of crashing with exceptions.

Ok.Thanks for advise.
I"ll try to use validate and will respond with results.

Hi Stephane.

  1. In code below you can see initialization of session parameters.
    .

.
.

/** Deploy */
val deploy = group(“Deploy”) {
exec(session => {
session
.set(“connectedModeStatus”, “None”)
.set(“flowStartTime”, System.currentTimeMillis())
.apply(session)
})
.exec(UserActions.deploy).pause(120 seconds).exec(UserActions.checkStability(“deploy”, true)) // let BIG IP 120 seconds for connection allocation
.exec(checkConnectedModeStatus)
.exec(session => {
session
.set(“flowEndTime”, (System.currentTimeMillis() - session(“flowStartTime”).as[Long]) / 1000)
.apply(session)
})
.exec(session => {
println(“Deploy time of user " + session(“username”).as[String] + " = " + session(“flowEndTime”).as[String] + " seconds .”)
session
})
}

  1. I tried to change my code as following , but nothing changed .it doesn’t work properly.
    What i do wrong ? thanks in advance .

/** Check if connected mode is ready (use Ping) */
val checkConnectedModeStatus = group(“Check Connected Mode”) {
asLongAs(_(“connectedModeStatus”).validate[String]== “None”, exitASAP = false) {
exec(getConnectingModeIndicator)
.doIfOrElse(session => {System.currentTimeMillis().toLong - session(“flowStartTime”).as[Long] > 600000.toLong}) { // println doesn’t appears
println(“ENTERING INSIDE!!!”)
exec(session => session.markAsFailed).exec(UserActions.checkStability(“connectedModeStatus”, true))
} {
println(“ENTERING OUTSIDE!!!”)
pause(10 seconds)
}
// if(session =>{System.currentTimeMillis().toLong - session(“flowStartTime”).as[Long] > 60000.toLong})
}
}

val getConnectingModeIndicator = http(“Check Connecting Mode is ready”)
.get(""“http://”"" + domain + “”"/sandbox/${testName}/${username}/in/flow/ping""")
.check(regex(""“sandbox.${testName}.${username}.in.flow”"").optional.saveAs(“connectedModeStatus”)) // when ping responds with 200OK connectedModeStatus is changed from “None” value to something else
.check(status.in(Seq(200, 0))).silent

Hi Greg,

Sorry for the late reply.

I think I noticed something very dangerous that could be your issue: you’re doing reference forwarding, ie use a reference before using it!
Scala let you use that because of some corner cases, but that’s the best way to get a NullPointerException. I think IDE’s would send you warnings for that.

getConnectingModeIndicator is a val and not a def, so it’s a reference, but it seems to be declared AFTER you try to use it, in checkConnectedModeStatus.

If I’m correct, you get a NullPointerException when evaluation the loop condition, causing it to be evaluated to false, hence exiting.

Could you please check this out before I investigate further, please?

I confirm that ScalaIDE sends you warnings for this.
And you should have a stacktrace in the logs.

Hi Stéphane.
I don’t get any NullPointerException .It just doesn’t work properly.
println doen’t work, so I don’t know what happened.
During this simulation my process should generate setup for additional simulation. current simulation are finishing , but setup didn’t been created.

I initialized connectedModeStatus and flowStartTime at the beginning of all test.
this is example number 1.
In example number 2. attached checkConnectedModeStatus group test, that has three println commands .No one has been displayed.
So at the end of Deploy group println ( println(“Deploy time of user " + session(“username”).as[String] + " = " + session(“flowEndTime”).as[String] + " seconds .”)) didn’t displayed.

Al this works fine only when I remark green highlighted code, but then I don’t have TimeOut handling.

any Ideas?
Thanks in advance.
Greg.

as below :

/** Deploy */
1. val deploy = group(“Deploy”) {
exec(session => {
session
.set(“connectedModeStatus”, “None”)
.set(“flowStartTime”, System.currentTimeMillis())
.apply(session)
})
.exec(UserActions.deploy).pause(120 seconds).exec(UserActions.checkStability(“deploy”, true))
.exec(checkConnectedModeStatus)
.exec(session => {
session
.set(“flowEndTime”, (System.currentTimeMillis().toLong - session(“flowStartTime”).as[Long]) / 1000)
.apply(session)
})
.exec(session => {
println(“Deploy time of user " + session(“username”).as[String] + " = " + session(“flowEndTime”).as[String] + " seconds .”)
session
})
}

2.

/** Check if connected mode is ready (use Ping) */
val checkConnectedModeStatus = group(“Check Connected Mode”) {
asLongAs(session => session(“connectedModeStatus”).as[String].contains(“None”), exitASAP = false) {
println(“AS LONG AS”)
exec(UserActions.getConnectingModeIndicator) //. pause(10 seconds)

.doIfOrElse(session => System.currentTimeMillis().toLong - session(“flowStartTime”).as[Long] > 60000.toLong) {
println(“WE ARE FAILED”)
exec(session => session.markAsFailed).exec(UserActions.checkStability(“connectedModeStatus”, true))
} {
println(“CONTINUE WORKING”)
pause(10 seconds)
}
}
}

Adding part of code of getConnectingModeIndicator

val getConnectingModeIndicator = http(“Check Connecting Mode is ready”)
.get(""“http://”"" + domain + “”"/sandbox/${testName}/${username}/in/flow/ping""")
.check(regex(""“sandbox.${testName}.${username}.in.flow”"").optional.saveAs(“connectedModeStatus”))
.check(status.in(Seq(200, 0))).silent

I think you didn’t get me.

What matters here is the order in which your vals are defined.

2 has to be defined BEFORE 1. If they are in the same file, you have to place 2 in front of 1.

If I change order of vals IDE shows “Reference to uninitialized value checkConnectedModeStatus”.

and simulation fails with :java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at io.gatling.mojo.MainWithArgsInFile.runMain(MainWithArgsInFile.java:50)
at io.gatling.mojo.MainWithArgsInFile.main(MainWithArgsInFile.java:33)
Caused by: java.lang.ExceptionInInitializerError
at breezeportal.SubModel.(SubModel.scala:28)
at breezeportal.Model.(Model.scala:10)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:379)
at io.gatling.core.runner.Runner.run(Runner.scala:36)
at io.gatling.app.Gatling$$anonfun$runSimulationIfNecessary$1.apply(Gatling.scala:132)
at io.gatling.app.Gatling$$anonfun$runSimulationIfNecessary$1.apply(Gatling.scala:117)
at scala.Option.getOrElse(Option.scala:121)
at io.gatling.app.Gatling.runSimulationIfNecessary(Gatling.scala:117)
at io.gatling.app.Gatling.start(Gatling.scala:73)
at io.gatling.app.Gatling$.fromArgs(Gatling.scala:59)
at io.gatling.app.Gatling$.main(Gatling.scala:44)
at io.gatling.app.Gatling.main(Gatling.scala)
… 6 more
Caused by: java.lang.NullPointerException
at io.gatling.core.structure.Execs$$anonfun$exec$1.apply(Execs.scala:30)
at io.gatling.core.structure.Execs$$anonfun$exec$1.apply(Execs.scala:30)
at scala.collection.immutable.List.flatMap(List.scala:327)
at io.gatling.core.structure.Execs$class.exec(Execs.scala:30)
at io.gatling.core.structure.ChainBuilder.exec(ChainBuilder.scala:30)
at io.gatling.core.structure.Execs$class.exec(Execs.scala:28)
at io.gatling.core.structure.ChainBuilder.exec(ChainBuilder.scala:30)
at breezeportal.Flows$.(Flows.scala:82)
at breezeportal.Flows$.(Flows.scala)
… 22 more

I transferred it to another file.
at the beginning of simulation were displayed all println’s
AS LONG AS
WE ARE FAILED
CONTINUE WORKING

and then simulation started and finished , but setup output didn’t been created.

I tried to define val checkConnectedModeStatus = group(“Check Connected Mode”) {…
as def checkConnectedModeStatus = {…
}
but nothing changed.

In addition there is some additional execS defined after exec(Deploy) in this test , but gatling doesn’t execute them .It stops simulation with OK status after exec(Deploy)

Instead of unreadable email code pasting, and shooting in the dark guessing, could you please upload an archive of your full code, please?

Stephane hi.
I found the problem .
Now it works fine.
The problem was in println rows…
val checkConnectedModeStatus = group(“Check Connected Mode”) {
asLongAs(_(“connectedModeStatus”).validate[String]== “None”, exitASAP = false) {
exec(getConnectingModeIndicator)

.doIfOrElse(session => {System.currentTimeMillis().toLong - session(“flowStartTime”).as[Long] > 600000.toLong}) { // println doesn’t appears
println(“ENTERING INSIDE!!!”)
exec(session => session.markAsFailed).exec(UserActions.checkStability(“connectedModeStatus”, true))
} {
println(“ENTERING OUTSIDE!!!”)
pause(10 seconds)
}

}
}

I changed them to :

/** Check if connected mode is ready (use Ping) */
def checkConnectedModeStatus = /group(“Check Connected Mode”)/ {
asLongAs(session => session(“connectedModeStatus”).as[String].contains(“None”), exitASAP = false) {
exec(UserActions.getConnectingModeIndicator).pause(10 seconds)
.doIfOrElse(session => System.currentTimeMillis().toLong - session(“flowStartTime”).as[Long] > 600000.toLong) {
exec(session => {
println("WE ARE FAILED !!! ")
session
})
.exec(session => session.markAsFailed).exec(UserActions.checkStability(“connectedModeStatus”, true))
} {
exec(session => {
println("CONTINUE PINGING F5… ")
session
}).
pause(10 seconds)
}
}
}

and that’s all…

Thanks for your time.

Oh, right!

What’s in {} block in the doIfOrElse branches are just some code that must return a DSL element. It’s only evaluated once, when the Simulation is created. You indeed have to wrap them inside exec(function) and chain them so they become a step in the scenario.

Glad you found it.

Thank you very much for your help and helpfulness.

You’re welcome, but here, I didn’t help much, you’re the one to credit :wink: