Gatling - how to handle if auth token expires while running the test?

My token expires in 2 hours, is there a way to refresh the token while executing the script to get the new token and continue the flow?

I do have a CSV file with 15000+ records, when ramping up users in the simulation file, it is supposed to make 300000 api invocations. I am wondering what if the token expires in the middle, Can you please advise how to handle if token expires in the middle in Gatling/Scala?

     .headers(header)       
  .check(status.is(200)).check(jsonPath("$.access_token").exists.saveAs("access_token")))

I capture access token and store as a session variable just once, and then run the simulation test with 5 users, since the csv file has 15000+ records, (used repeat from gatling) it invokes 5 users*150000 csv records= 300000 api calls. thought that it is not a good idea to get the token each time, for 300000 api calls, but wondering the same time what if token expires in the middle of the execution, Can you please advise how to make sure to process all 300000 api calls successfully with the valid token, is there a way to get the token only when it is expired to continue the flow, rather than getting the token for each api call? Please advise.

rampUsers(20).during(50), and i do have 20*15000 records=300000 api calls

You have 2 options:

  1. renew the token preemptively: in your loop, use a doIf to periodically test the elapsed time and if the token is about to expire, renew it
  2. renew the token on expiration: on each request, save the status with a check and after the request, using a doIf, renew the token if the status was a token expiration.

i have a question on the option 2. if the request is failing for the expired token , and using doif trigger the post request with the valid token after the renewal, will it not in the first place -(the first time the request was made with expired token) log failures in the report (or) capture error messages in the log file? and will retry with doif remove the error message from the report/or log and overwrite the response status with successful response that is processed with the valid token the second time?
just want to make sure if the report/log files look cleaner with no error messages on it? Can you please clarify.

The failed request will be logged and counted as a failure.

ok, Thank you for the clarification. I found the answer that you recommended, and i do have a question that I want to clarify please.
Recommended answer by you:
Pseudo code (in Java, supported since Gatling 3.7):

// global mutable reference to a shared token
private volatile String token = null;

// first scenario refreshes the token
// must run with one single user 
ScenarioBuilder refresh = scenario("refresh")
.during(Duration.ofHours(3)).on(
  exec(http("refreshToken").get(???).check(saveToken))
  .exec(session ->
    {
      token = session.getString("token")
      return token;
    }
  ).pause(Duration.ofMinutes(15))
);


// second scenario uses the token,
// must start after the first one
ScenarioBuilder use = scenario("use")
  .exec(http("useToken").get(???).header("Bearer", session -> token))

From you answer, In this case should refresh scenario be called like below with 1 user then use scenario will reuse the token ?but since we run refresh scenario outside use, with just 1 user, wondering how refresh simulation will run again when the token expires? my understanding is that. when we run with 1 user, it only runs once. hence refresh scenario is done running with just 1 user , wondering how it can go back and run again when use scenario token expires?

Can you please confirm if the setup block listed below is how the setup block is supposed to be built?

Option a:
setUp(
refresh.inject(
nothingFor(1),
atOnceUsers(1),
).andThen(use.inject(nothingFor(1),
atOnceUsers(1),
rampUsers(10).during(50))))

(or)
Option b:
val test: ScenarioBuilder =
scenario(“Simulation”)
.exec(refresh)
.exec(use)

setUp(
test.inject(
nothingFor(1),
atOnceUsers(1),
rampUsers(10).during(50)))

Can you please advise how to build the setup block here to build the flow you provided in your answer above?

This code creates a shared token but doesn’t refresh it periodically. You could have the token scenario loop with a pause. But then the actual scenario can’t wait for it to start, so you’ll have to start after a short delay to make sure the first token is fetched.

Can you please clarify why the token scenario loop should have a pause? From the code above, i thought the token refreshes for every 15 mins , when you say to add a pause , do you mean to add a pause in the refresh scenario in the setup block in the simulation file?

I understood the above comment quoted here,to add a short delay for the actual scenario to wait, however i dont understand why the refresh scenario block also should have a pause, Can you please clarify how the pause in the token scenario helps here?

The pause would be the duration between 2 refreshes.

I’m afraid I’ve gone as far as can help here. You might want to consider getting consulting/mentoring.

realized that you were referring to Pace with forever loop- a special kind of Pause, that makes sense, to wait between two refreshes, thank you, Can you please confirm if i understood correctly?

Secondly, Without forever , the auth_token_refresh did not run for every 2 minutes, with pace. Hence i added forever,
Next i ran refresh_token and submitOrders scenarios (submitOrders with a short delay)… Can you please confirm if it looks ok?

def auth_token_refresh = scenario(“Access Token Generation”)
.forever {
pace(120). – for testing running this for every 2 minutes.
.exec(
http(“Refresh token”)
.post(“https://api.com”)
.basicAuth(“1238284”, “adjfhdsjhf”)
.queryParam(“grant_type”, “client_credentials”)
.headers(header)
.check(status.is(200)).check(jsonPath(“$.access_token”).exists.saveAs(“access_token”)))
}

setUp(
OrderSimulation_round1.inject(
nothingFor(1),
atOnceUsers(1),
).andThen(openOrders.inject(nothingFor(1),
atOnceUsers(1)).
andThen(
refresh_token.inject(nothingFor(1),
atOnceUsers(1)),
submitOrders.inject(nothingFor(1),
atOnceUsers(1),
rampUsers(6).during(50))). —> this has repeat method, that will execute 300000 plus records, that
needs refreshed token for every 2 hours.
andThen(closeOrders.inject(nothingFor(1),
atOnceUsers(1)))
))

however in this case, i noticed that refresh_token scenario gets executed for every 2 mins, but it is inside its own virtual user session , and wondering how the refresh token can be shared inside submitOrders virtual user session? i believe , the data cant be shared between virtual users, can you please confirm, if so can you please advise how i can then use pace here to refresh token. Thank you for your time, looking forward…

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.