@@ -46,6 +46,12 @@ def cli_custom_arguments(parser: LocustArgumentParser):
46
46
)
47
47
48
48
49
+ def send_msg_to_workers (master_runner : MasterRunner , msg_type : str , data : dict [str , t .Any ]):
50
+ for i , worker in enumerate (master_runner .clients ):
51
+ master_runner .send_message (msg_type , {"data" : (data , i )}, worker )
52
+ logger .debug (f"{ msg_type } sent to worker { i } " )
53
+
54
+
49
55
def setup_test_data (environment : Environment , msg : Message , ** kwargs ):
50
56
# Fired when the worker receives a message of type 'test_data'
51
57
test_data : dict [str , t .Any ] = msg .data ["data" ][0 ]
@@ -61,15 +67,25 @@ def setup_test_data(environment: Environment, msg: Message, **kwargs):
61
67
user .test_data .init_network (chain_id )
62
68
else :
63
69
raise AttributeError (f"{ user } class does not have 'test_data' attribute" )
64
- environment .runner .send_message ("acknowledge_data" , {"data" : f"Test data received by worker { worker_index } " })
65
- logger .info ("Test Data received from master" )
70
+ environment .runner .send_message (
71
+ "acknowledge_data" , {"data" : f"Initial test data received by worker { worker_index } " }
72
+ )
73
+ logger .info ("Initial test data received from master" )
66
74
67
75
68
76
def on_acknowledge (msg : Message , ** kwargs ):
69
77
# Fired when the master receives a message of type 'acknowledge_data'
70
78
print (msg .data ["data" ])
71
79
72
80
81
+ def on_release (environment : Environment , msg : Message , ** kwargs ):
82
+ # Fired when the worker receives a message of type 'release_lock'
83
+ if isinstance (environment .runner , WorkerRunner ):
84
+ for user in environment .runner .user_classes :
85
+ if hasattr (user , "test_data" ):
86
+ user .test_data .release_lock ()
87
+
88
+
73
89
def get_block_worker (master_runner : MasterRunner ):
74
90
logger .info ("Getting blocks in real time." )
75
91
active_users : list [t .Type [User ]] = []
@@ -104,15 +120,13 @@ def get_block_worker(master_runner: MasterRunner):
104
120
blocks [test_data_class_name ] = block .to_json ()
105
121
print (f"Block { block .block_number } fetched and updated in test data" )
106
122
if len (blocks ) > 0 :
107
- for i , worker in enumerate (master_runner .clients ):
108
- master_runner .send_message ("block_data" , {"data" : blocks }, worker )
109
- logger .info (f"Block data is sent to worker { i } " )
123
+ send_msg_to_workers (master_runner , "block_data" , blocks )
110
124
time .sleep (1 )
111
125
112
126
113
127
def on_receive_block (environment : Environment , msg : Message , ** kwargs ):
114
128
# Fired when the worker receives a message of type 'block_data'
115
- blocks : dict [str , t .Any ] = msg .data ["data" ]
129
+ blocks : dict [str , t .Any ] = msg .data ["data" ][ 0 ]
116
130
117
131
if isinstance (environment .runner , WorkerRunner ):
118
132
for user in environment .runner .user_classes :
@@ -121,7 +135,7 @@ def on_receive_block(environment: Environment, msg: Message, **kwargs):
121
135
block : Block = user .test_data .get_block_from_data (blocks [test_data_class_name ])
122
136
if block .block_number not in user .test_data .data .block_numbers :
123
137
user .test_data .data .push_block (block )
124
- logger .debug (f"Block { block .block_number } received from master and updated in test data" )
138
+ logger .info (f"Block { block .block_number } received from master and updated in test data" )
125
139
126
140
127
141
# Listener for the init event
@@ -138,8 +152,7 @@ def on_init(environment: Environment, **_kwargs):
138
152
logger .info ("I'm a worker. Running tests for %s" , host_under_test )
139
153
environment .runner .register_message ("test_data" , setup_test_data )
140
154
environment .runner .register_message ("block_data" , on_receive_block )
141
-
142
- test_data : dict [str , t .Any ] = {}
155
+ environment .runner .register_message ("release_lock" , on_release )
143
156
144
157
if isinstance (environment .runner , MasterRunner ):
145
158
# Print master details to the log
@@ -156,6 +169,7 @@ def on_init(environment: Environment, **_kwargs):
156
169
raise exit (1 )
157
170
time .sleep (1 )
158
171
try :
172
+ test_data : dict [str , t .Any ] = {}
159
173
for user in environment .runner .user_classes :
160
174
if not hasattr (user , "test_data" ):
161
175
raise AttributeError (f"{ user } class does not have 'test_data' attribute" )
@@ -174,19 +188,50 @@ def on_init(environment: Environment, **_kwargs):
174
188
print (f"Target endpoint network is { user_test_data .network .name } " )
175
189
test_data ["chain_id" ] = {test_data_class_name : chain_id }
176
190
if environment .parsed_options :
177
- user_test_data .init_data_from_blockchain (environment .parsed_options )
191
+ user_test_data .init_data (environment .parsed_options )
178
192
test_data [test_data_class_name ] = user_test_data .data .to_json ()
193
+ send_msg_to_workers (environment .runner , "test_data" , test_data )
194
+ print ("Fetching blocks..." )
195
+ if environment .parsed_options .use_latest_blocks :
196
+ print (f"Using latest { user_test_data .data .size .blocks_len } blocks as test data" )
197
+ logger .info (f"Using latest { user_test_data .data .size .blocks_len } blocks as test data" )
198
+ for block_number in range (
199
+ user_test_data .data .block_range .start , user_test_data .data .block_range .end + 1
200
+ ):
201
+ try :
202
+ block = user_test_data .fetch_block (block_number )
203
+ except (BlockNotFoundError , InvalidBlockError ):
204
+ block = user_test_data .fetch_latest_block ()
205
+ user_test_data .data .push_block (block )
206
+ block_data = {test_data_class_name : block .to_json ()}
207
+ send_msg_to_workers (environment .runner , "block_data" , block_data )
208
+ print (user_test_data .data .stats (), end = "\r " )
209
+ else :
210
+ print (user_test_data .data .stats (), end = "\r " )
211
+ print ("\n " ) # new line after progress display upon exiting loop
212
+ else :
213
+ while user_test_data .data .size .blocks_len > len (user_test_data .data .blocks ):
214
+ try :
215
+ block = user_test_data .fetch_random_block (user_test_data .data .block_numbers )
216
+ except (BlockNotFoundError , InvalidBlockError ):
217
+ continue
218
+ user_test_data .data .push_block (block )
219
+ block_data = {test_data_class_name : block .to_json ()}
220
+ send_msg_to_workers (environment .runner , "block_data" , block_data )
221
+ print (user_test_data .data .stats (), end = "\r " )
222
+ else :
223
+ print (user_test_data .data .stats (), end = "\r " )
224
+ print ("\n " ) # new line after progress display upon exiting loop
225
+ logger .info ("Test data is ready" )
226
+ send_msg_to_workers (environment .runner , "release_lock" , {})
227
+ user_test_data .release_lock ()
179
228
except Exception as e :
180
- logger .error (f"Failed to update test data: { e .__class__ .__name__ } : { e } . Exiting..." )
181
- print (f"Failed to update test data:\n { e .__class__ .__name__ } : { e } . Exiting..." )
229
+ logger .error (f"Failed to init test data: { e .__class__ .__name__ } : { e } . Exiting..." )
230
+ print (f"Failed to init test data:\n { e .__class__ .__name__ } : { e } . Exiting..." )
182
231
logger .debug (traceback .format_exc ())
183
232
environment .runner .quit ()
184
233
raise exit (1 )
185
234
else :
186
- logger .info ("Test data is ready" )
187
- for i , worker in enumerate (environment .runner .clients ):
188
- environment .runner .send_message ("test_data" , {"data" : (test_data , i )}, worker )
189
- logger .info (f"Test data is sent to worker { i } " )
190
235
if environment .web_ui :
191
236
print (f"Web UI started at: " f"http://{ environment .runner .master_bind_host } :8089" )
192
237
logger .info (f"Web UI started at: " f"http://{ environment .runner .master_bind_host } :8089" )
0 commit comments