How to send object in worker from master?

Is have code

class Tasks(SequentialTaskSet):
    @task
    def shopping(self):
        with self.parent.environment.parsed_options.shopping.request_airshopping(
                client=self.client, catch_response=True) as response:
            self.run_req(response, self.parent.environment.parsed_options.rsa)

class WebUser(HttpUser):
    tasks = [Tasks]
    min_wait = 0
    max_wait = 0

    @staticmethod
    @events.test_start.add_listener
    def on_test_start(environment: Environment, **kwargs):
        os.environ["ENABLE_SLEEP"] = "False"
        credentials = {
            "login": environment.parsed_options.login,
            "password": environment.parsed_options.password,
            "structure_unit_code": environment.parsed_options.suid,
        }
        login = Login(base_url=environment.host)
        response = login.request_login(credentials)
        parse_xml = parsing_xml_response(response.text)
        headers = {
            "Content-Type": "application/xml",
            "Authorization": f'Bearer {parse_xml.xpath("//Token")[0].text}'}
        shopping = Shopping(
            base_url=environment.parsed_options.host,
            headers=headers
        )
        set_paxs(environment, shopping)
        set_flight(environment, shopping)
        environment.parsed_options.__dict__.update({"shopping": shopping})

If start without worker - success working

If start workers - errors: TypeError: can not serialize 'Shopping' object

How to send object Shopping in worker from master?

Try https://docs.locust.io/en/stable/running-distributed.html

Upvotes: 0

Views: 610

Answers (1)

Solowalker
Solowalker

Reputation: 2856

You can do this by sending a message from worker to master or master to worker. The message is just a string but you can include a data payload with it. You need a function that registers what your message is and what to do when it receives that message, which many times will be a function that does something with the data payload. The docs use this example:

from locust import events
from locust.runners import MasterRunner, WorkerRunner

# Fired when the worker receives a message of type 'test_users'
def setup_test_users(environment, msg, **kwargs):
    for user in msg.data:
        print(f"User {user['name']} received")
    environment.runner.send_message('acknowledge_users', f"Thanks for the {len(msg.data)} users!")

# Fired when the master receives a message of type 'acknowledge_users'
def on_acknowledge(msg, **kwargs):
    print(msg.data)

@events.init.add_listener
def on_locust_init(environment, **_kwargs):
    if not isinstance(environment.runner, MasterRunner):
        environment.runner.register_message('test_users', setup_test_users)
    if not isinstance(environment.runner, WorkerRunner):
        environment.runner.register_message('acknowledge_users', on_acknowledge)

The @events.init.add_lisenter means Locust will run that function when it starts up and the key part is that register_message call. The first argument is an arbitrary string, whatever you want it to be. The second argument is the function to call when that message is received.

Note the arguments the function to be called has defined. One of them is msg, which you need to use to get the data that is sent.

Then you can send the message and data payload any time you want. The docs use this example:

users = [
        {"name": "User1"},
        {"name": "User2"},
        {"name": "User3"},
    ]
environment.runner.send_message('test_users', users)

The string is the message you want the receiver to match and the second argument users in this case is the actual data you want to send to the other instance(s).

Upvotes: 1

Related Questions