Add async argument in CodeBlock

If CodeBlocks contain time-consuming logic (e.g. API calls) they block the web server. The proposal is to add an async argument to the CodeBlock constructor that makes this logic perform asynchronously via WorkerAsyncProcess. The logic looks something like this:

  • A CodeBlock that initializes a WorkerAsyncProcess using the WorkerAsyncProcess constructor. The process should have the label CodeBlock so that we know where it comes from. See example code:

        WorkerAsyncProcess(
            label="CodeBlock",
            function=self._request_partial_payment,
            arguments={
                "participant": participant,
                "payment": participant.calculate_reward(),
                # "reason": _("Partial payment for incomplete participation"),
            },
            participant=participant,
            unique=dict(participant_id=participant.id),
        )
  • A wait_while that waits for this process to complete. Something like:
    def code_block_process_finished(participant):
        relevant_processes = [
            p
            for p in participant.async_processes
            if p.label == "CodeBlock"
        ]
        assert len(relevant_processes) == 1
        process = relevant_processes[0]

        assert not process.failed
        return process.finished


       wait_while(
            condition=lambda participant: not code_block_process_finished(participant),
            expected_wait=5.0,
            check_interval=2.0,
        )

We should have a test for this new feature. I propose creating a very simple demo that goes in the 'features' directory that has an async code block with a time.sleep() in it followed by setting a participant variable, and then a test assertion in def test_check_bot that checks that the variable got set correctly.

Edited by Peter Harrison