1111import gevent .lock
1212import pandas as pd
1313from botocore .config import Config
14- from locust import HttpUser , constant_throughput , events , task
14+ from locust import constant_throughput , events , task
15+ from locust .contrib .fasthttp import FastHttpUser
16+ from locust .runners import WorkerRunner
1517
1618from common .api_clients .authentication import AppRestrictedAuth
1719
2931
3032_BOTO_CONFIG = Config (
3133 max_pool_connections = 50 , # default is 10; needs to exceed max concurrent Locust users
32- retries = {"mode" : "standard" , "max_attempts" : 3 },
34+ retries = {"mode" : "standard" , "max_attempts" : 1 },
3335)
3436_secrets_client = boto3 .client (
3537 "secretsmanager" ,
3840)
3941
4042PERF_CREATE_TASK_RPS_PER_USER = float (os .getenv ("PERF_CREATE_RPS_PER_USER" , "1" ))
43+ PERF_SEARCH_RPS_PER_USER = float (os .getenv ("PERF_SEARCH_RPS_PER_USER" , "1" ))
4144
4245IMMUNIZATION_TARGETS = [
4346 "3IN1" ,
@@ -112,7 +115,13 @@ def get_access_token(self) -> str:
112115
113116@events .init .add_listener
114117def _pre_warm_auth (environment , ** kwargs ):
115- """Fetch token once before users spawn so all users start with a cached token."""
118+ """Fetch token once before users spawn so all users start with a cached token.
119+ Only runs on master/standalone — workers fetch lazily on first request,
120+ staggered by the on_start jitter, avoiding simultaneous Secrets Manager calls.
121+ """
122+ if isinstance (environment .runner , WorkerRunner ):
123+ return
124+
116125 try :
117126 token = _shared_token_manager .get_access_token ()
118127 print (f"[perf] Auth pre-warm complete. Token length: { len (token )} " )
@@ -126,16 +135,14 @@ def _pre_warm_auth(environment, **kwargs):
126135 "\n [perf] FATAL: AWS credentials expired or inaccessible.\n "
127136 f" Error: { exc } \n \n "
128137 " Fix: run one of the following, then retry 'make test':\n "
129- " aws sso login --sso-session akshay-sso\n "
130138 " aws sso login --profile <your-profile-name>\n " ,
131139 file = sys .stderr ,
132140 )
133141 sys .exit (1 )
134- # Non-credential error — re-raise so it's not silently swallowed
135142 raise
136143
137144
138- class BaseImmunizationUser (HttpUser ):
145+ class BaseImmunizationUser (FastHttpUser ):
139146 abstract = True
140147
141148 # token_manager = LocustTokenManager(
@@ -164,7 +171,7 @@ def on_start(self):
164171
165172 def _build_create_payload (self ):
166173 immunization_target = random .choice (IMMUNIZATION_TARGETS )
167- patient = load_patient_by_id (random . choice ( VALID_PATIENT_IDS ) )
174+ patient = load_patient_by_id ("Valid_NHS" )
168175 immunization = create_immunization_object (patient , immunization_target )
169176 return json .loads (immunization .json (exclude_none = True ))
170177
@@ -183,7 +190,7 @@ def _delete_created_immunization(self, immunization_id: str):
183190
184191
185192class SearchUser (BaseImmunizationUser ):
186- wait_time = constant_throughput (1 )
193+ wait_time = constant_throughput (PERF_SEARCH_RPS_PER_USER )
187194
188195 @task
189196 def search_single_vacc_type (self ):
0 commit comments