Skip to content

chore: remove async/await from websocket-client send operations and convert the test to use synchronous library#1918

Open
Harsh16gupta wants to merge 6 commits intoasyncapi:masterfrom
Harsh16gupta:bug/async-await-1857-clean
Open

chore: remove async/await from websocket-client send operations and convert the test to use synchronous library#1918
Harsh16gupta wants to merge 6 commits intoasyncapi:masterfrom
Harsh16gupta:bug/async-await-1857-clean

Conversation

@Harsh16gupta
Copy link
Contributor

@Harsh16gupta Harsh16gupta commented Feb 2, 2026

Description

Fixes async/sync mismatch in the Python WebSocket client template. The template used async/await with the synchronous websocket-client library, causing runtime errors.

This PR:

  • Removes async/await from send operations
  • Convert test to use synchronous websockets.sync library

Fixes #1857

Screenshots
Templates
Python WebSocket Client
image
Client for Slack
image
Client for Slack with Auto-Routing
image

Acceptance test
image
image

Summary by CodeRabbit

  • Refactor

    • Python WebSocket send helpers and client send methods converted from asynchronous to synchronous execution while preserving behavior and error handling.
    • Message-discriminator logic simplified to a single conditional expression, removing an early-return guard.
  • Tests

    • Acceptance tests converted from async/await to a synchronous, thread-driven server lifecycle; startup/shutdown and timing now use thread coordination and blocking waits, and expected test message flow updated.

@changeset-bot
Copy link

changeset-bot bot commented Feb 2, 2026

⚠️ No Changeset found

Latest commit: 4223b1f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link

coderabbitai bot commented Feb 2, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Replaces async function declarations and await expressions with synchronous definitions and direct calls in generated Python WebSocket client code and tests; also simplifies discriminator computation by replacing an early-return guard with a conditional assignment.

Changes

Cohort / File(s) Summary
Python WebSocket Send operations
packages/components/src/components/SendOperations.js
Generated instance and static send methods changed from async def ... with await ... to synchronous def ... and direct calls to _send (no await).
Python WebSocket Send template helper
packages/templates/clients/websocket/python/components/Send.js
Converted helper _send from async def _send(message, socket) using await socket.send(message) to synchronous def _send(message, socket) calling socket.send(message).
Receive operations discriminators
packages/templates/clients/websocket/python/components/ReceiveOperationsDiscriminators.js
Removed early-return guard; operationDiscriminators now set via conditional expression: getMessageDiscriminatorsFromOperations(receiveOperations) if present, else [], preserving subsequent serialization/rendering.
WebSocket Python tests (sync conversion)
packages/templates/clients/websocket/test/python/test_acceptance.py
Converted async test and handler to synchronous versions using websockets.sync.server and threading; replaced asyncio/await with thread/event lifecycle and time.sleep; adjusted expected payload direction.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The pull request fully addresses all coding objectives from issue #1857: removing async/await from generated Python WebSocket client send operations, converting to synchronous code compatible with websocket-client library, and providing working tests.
Out of Scope Changes check ✅ Passed All changes are within scope: SendOperations.js and Send.js templates convert async to sync send operations; ReceiveOperationsDiscriminators.js refactors discriminator initialization; test_acceptance.py updates tests to use synchronous server handling—all directly supporting the async/await removal objective.
Title check ✅ Passed The title accurately describes the main changes: removing async/await from WebSocket send operations and converting tests to synchronous handling, following Conventional Commits with 'chore:' prefix.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/components/src/components/SendOperations.js (1)

30-37: ⚠️ Potential issue | 🟡 Minor

Fix Python docstrings to reference correct WebSocket type.

The docstring incorrectly references websockets.WebSocketCommonProtocol (async library), but the codebase uses the synchronous websocket-client library (import websocket in DependencyProvider.js). The socket parameter should be typed as websocket.WebSocketApp. This same error also appears in packages/templates/clients/websocket/python/components/Send.js line 19.

Proposed changes

SendOperations.js (line 36):

-        socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.
+        socket (websocket.WebSocketApp): The WebSocket to send through.

Send.js (line 19):

-        socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.
+        socket (websocket.WebSocketApp): The WebSocket to send through.
packages/templates/clients/websocket/python/components/Send.js (1)

12-27: ⚠️ Potential issue | 🟡 Minor

Fix incorrect WebSocket type in the _send method docstring.

The docstring references websockets.WebSocketCommonProtocol (async library), but this template uses the synchronous websocket-client library and passes self.ws_app, which is a WebSocketApp instance. Update the type annotation to match:

Suggested change
-        socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.
+        socket (websocket.WebSocketApp): The WebSocket to send through.
🧹 Nitpick comments (2)
packages/templates/clients/websocket/python/components/Send.js (1)

3-33: Add JSDoc for the Send component (params/returns/errors).

The exported Send function lacks JSDoc, which is required for JS files. Please include param types, return type, and error conditions (even if “none”).

🧾 Suggested JSDoc
 export function Send({ sendOperations }) {
+/**
+ * Renders the Python _send helper when send operations exist.
+ *
+ * `@param` {{ sendOperations: Array<Object> }} props - Component props.
+ * `@returns` {JSX.Element|null} Rendered helper code or null when no operations exist.
+ * `@throws` {Error} Does not throw.
+ */
+export function Send({ sendOperations }) {
packages/components/src/components/SendOperations.js (1)

105-113: Complete JSDoc for SendOperations with return and error info.

The existing JSDoc omits @returns and error conditions, which are required for JS files.

🧾 Suggested JSDoc completion
 /**
  * Component for rendering WebSocket send operation methods.
  * Generates both static and instance methods for sending messages through WebSocket connections.
  *
  * `@param` {Object} props - Component props.
  * `@param` {SupportedLanguage} props.language - The target programming language.
  * `@param` {Array<Object>} props.sendOperations - Array of send operations from AsyncAPI document.
  * `@param` {string} props.clientName - The name of the client class.
+ * `@returns` {Array<JSX.Element>|null} Rendered operation methods or null when there are no send operations.
+ * `@throws` {Error} Does not throw.
  */
 export function SendOperations({ language, sendOperations, clientName }) {

@Harsh16gupta
Copy link
Contributor Author

@Adi-204 I tried to look at the failed test but can't figure out why it is failing, please guide. All executed checks (SonarCloud, CodeRabbit) are passing. Please let me know if you’d like me to rerun anything after approval.

@Adi-204 Adi-204 self-assigned this Feb 3, 2026
@Adi-204 Adi-204 moved this to In Progress in Maintainers work Feb 3, 2026
Copy link
Member

@Adi-204 Adi-204 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Harsh16gupta acceptance test for python are failing please look into it and in the PR desc I was expecting screenshots of running clients with python example.py command and not the test results.

@Harsh16gupta
Copy link
Contributor Author

@Harsh16gupta acceptance test for python are failing please look into it and in the PR desc I was expecting screenshots of running clients with python example.py command and not the test results.

@Adi-204 thanks for the review, and sorry for the misunderstanding.
Initially the tests were failing, so I was updating the snapshots and added those screenshots to the description. I understand now that screenshots of the client running via python example.py are expected. I’ll update the PR accordingly and fix the failing Python acceptance tests.

@Harsh16gupta
Copy link
Contributor Author

@Adi-204 I've investigated the failing Python acceptance test and found.

The Issue

The acceptance test file (packages/templates/clients/websocket/test/python/test_acceptance.py) has a mismatch between WebSocket libraries:

  1. The generated client (after my PR fix): Uses the synchronous websocket-client library
  2. The test's WebSocket server: Uses the asynchronous websockets library

In test_hoppscotch_client_sends_message(), the test tries to call:

await HoppscotchEchoWebSocketClient.send_echo_message_static(expected_outgoing_message, websocket)

But:

  • My PR correctly made send_echo_message_static() synchronous (removing async/await)
  • The websocket parameter comes from the websockets library (async), not websocket-client
  • These are two completely different libraries with incompatible APIs

Proposed Solution

I see two approaches:

Option 1: Send directly in the test (simpler)

async def handler(websocket):
    message = expected_outgoing_message
    if isinstance(message, dict):
        message = json.dumps(message)
    await websocket.send(message)  # Use websockets library directly

This replicates the client's message formatting logic without mixing libraries.

Option 2: Refactor test to use websocket-client
Make the test server also use websocket-client, but this requires more significant test infrastructure changes.

Question

Which approach would you prefer?
Please let me know your preference, and I'll implement it right away!

@Harsh16gupta
Copy link
Contributor Author

@Adi-204 Since the last test-related PR has been merged, I wanted to check if I can go ahead and start working on #1887.

@Adi-204
Copy link
Member

Adi-204 commented Feb 4, 2026

hey @Harsh16gupta first let's wait for https://asyncapi.slack.com/archives/C072JMTJ85Q/p1770225233478619
to be 100% sure and can you please explain Option 1 in more detail?

@Harsh16gupta
Copy link
Contributor Author

Harsh16gupta commented Feb 4, 2026

@Adi-204 Sorry for not updating the screenshots until now. I was using WSL, and the command
pip install -r test/temp/snapshotTestResult/custom_client_hoppscotch/requirements.txt
was not working there, so I was unable to run the snapshot tests at that time.

During the current debugging (after my PR fix),
image

I found that the Python generated client.py (for postman) does not include:

self.receive_operation_handlers = {}
self.receive_operation_discriminators = []

Because of this, the runtime crashes when on_message tries to access these attributes. To verify this, I manually added these lines to the generated client.py:

image

After adding them, the runtime error was resolved. This confirmed that the issue was caused by missing initialization in the generated client.

The main question then was why this is generated for Hoppscotch but not for Postman. While tracing the generator logic, in the file
packages\templates\clients\websocket\python\components\ReceiveOperationsDiscriminators.js
I found that this was due to conditional handling of receiveOperation so I changed it to:
before

const hasOperations = Array.isArray(receiveOperations) && receiveOperations.length > 0;
  if (!hasOperations) {
    return null;
  }

  const operationDiscriminators = getMessageDiscriminatorsFromOperations(receiveOperations);

after

const operationDiscriminators =
  Array.isArray(receiveOperations) && receiveOperations.length > 0
    ? getMessageDiscriminatorsFromOperations(receiveOperations)
    : [];

With this change, the constructor always initializes the required fields and uses an empty list when there are no receive operations.
I then ran everything again, and the correct client.py was generated.
Final output:

image

Waiting for your approval before committing all these changes.
Thank you.

@Harsh16gupta
Copy link
Contributor Author

Harsh16gupta commented Feb 5, 2026

can you please explain Option 1 in more detail?

So the main problem for the failing of the test was that we are using websockets (Asynchronous) in the test server

async def handler(websocket):
    await HoppscotchEchoWebSocketClient.send_echo_message_static(
        expected_outgoing_message, 
        websocket  # wrong library
    )

But send_echo_message_static() expects a socket from websocket-client library (sync)


@staticmethod
  def _send(message, socket):
      """
      Internal helper to handle the actual sending logic.

      Args:
          message (dict or str): The message to send.
          socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.

      Notes:
          If message is a dictionary, it will be automatically converted to JSON.
      """
      try:
          if isinstance(message, dict):
              message = json.dumps(message)
          socket.send(message)
      except Exception as e:
          print("Error sending:", e)

So instead of calling the client’s send method from the async test server, the test sends the message directly using the websockets library, while replicating the same message-formatting logic used by the client:

// IN the client.py we use this 
async def handler(websocket):
    message = expected_outgoing_message
    if isinstance(message, dict):
        message = json.dumps(message)
    await websocket.send(message)

so I changed the test server with the option 1 (to use the same logic )

async def handler(websocket):
        ###############
        #
        # Most important part of test where we test clients send message
        #
        ###############
        message = expected_outgoing_message
    
        if isinstance(message, dict):
            message = json.dumps(message)
        
        await websocket.send(message)

and then ran the test locally
image
image
and then the test passed

What I concluded from this:

  • We should not call the client’s static send method from an async test server
  • Instead, the test should replicate the client’s message-formatting logic
  • The message should then be sent directly using the websockets library
  • Microcks validates the message payload against the AsyncAPI spec
  • If Microcks accepts it, that confirms the client would send a correctly formatted message

so what do you think, is the approach good?

@Harsh16gupta
Copy link
Contributor Author

Dart template

image

Js template

image While testing the JavaScript template, I found a small issue in the README.
By default this is testing against Hoppscotch echo service. You can modify `packages/templates/clients/websocket/javascript/example.js` and change first line to `const WSClient = require('./tests/temp/snapshotTestResult/client_postman/client.js');` and run `node example.js` again. You will see example still works but now it is using a different API. This is possible since both AsyncAPI documents define the same name of operation for sending messages: `sendEchoMessage` so each client generated has the same API.

The README currently mentions the following path: ./tests/temp/snapshotTestResult/client_postman/client.js is wrong
However, the correct path is:
./test/temp/snapshotTestResult/client_postman/client.js

Java template

image

Python template

image

All templates (Dart, JavaScript, Java, and Python) were verified by running them locally after applying the discussed fixes, and all are working correctly.

Please let me know if you’re okay with me committing all the remaining changes based on this.
Thank you for your time and review

@Harsh16gupta Harsh16gupta requested a review from Adi-204 February 6, 2026 11:18
Copy link
Member

@Adi-204 Adi-204 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Harsh16gupta I checked your proposed solution option 1 in detail. I don't think we can go with that solution, because basically you are replacing await HoppscotchEchoWebSocketClient.send_echo_message_static with same logic but let's say someone makes changes in send_echo_message_static it will not get tested with acceptance test as you just hardcode logic in acceptance test and it will pass always.

We also have comment Most improtant part of test where we test clients send message which also suggest you have to use generated client to test for send functionality and you are suggesting to remove this?

@Harsh16gupta
Copy link
Contributor Author

@Adi-204 Thank you for the detailed feedback. I understand your concern now.

Option 1 doesn't actually test the client's send method. If someone modifies the client's _send() logic in the future, the test would still pass because it's using hardcoded logic instead of the actual client code. This defeats the purpose of the acceptance test. But we can't directly pass an async websockets socket to the client's synchronous send_echo_message_static() method.
This is why I went with Option 1, to work around the library incompatibility (I thought the best way to do this is by doing it hardcoded but didn't think about the future changes). But I see now that this approach sacrifices the test's actual purpose.

What's the recommended approach to solve this? Should I:

  1. Change the test infrastructure to use a synchronous WebSocket server library?
  2. Keep the test as it is and make a switch to Async WebSocket Library?
  3. A different approach you'd suggest?

Please let me know your preference and I'll update the PR accordingly.
Thank you for your patience!

@Adi-204
Copy link
Member

Adi-204 commented Feb 7, 2026

@Harsh16gupta I tried to debug locally and find a solution such that we don't need to do a lot of code changes, but that doesn't seem to be easy task.

Two options

  1. Sync operations use websocket-client (Make changes in Acceptance test infra)
  2. Async operations use websockets (Make changes in Generated client)

I checked with option 2 we will have to make a lot of changes and I'm not 100% sure about how much changes needs to done in option 1 as acceptance test was setup by @derberg so he is the best person to know about that. Maybe you can try analyze acceptance test infra, @derberg wdyt 🤔 ? approach should we go for?

@Harsh16gupta
Copy link
Contributor Author

@Adi-204 That makes sense, thanks for digging into it.
I’ll try both approaches locally (adjusting the acceptance test infra vs. switching the generated client) and share my findings.
Since this issue is critical, would it be okay if I open separate PRs for the two additional issues I discovered during debugging, so we can keep concerns isolated and easier to review?

1st one

I found that the Python generated client.py (for postman) does not include:

self.receive_operation_handlers = {}
self.receive_operation_discriminators = []

Because of this, the runtime crashes when on_message tries to access these attributes. To verify this, I manually added these lines to the generated client.py:

2nd one
While testing the JavaScript template, I found a small issue in the README.

By default this is testing against Hoppscotch echo service. You can modify `packages/templates/clients/websocket/javascript/example.js` and change first line to `const WSClient = require('./tests/temp/snapshotTestResult/client_postman/client.js');` and run `node example.js` again. You will see example still works but now it is using a different API. This is possible since both AsyncAPI documents define the same name of operation for sending messages: `sendEchoMessage` so each client generated has the same API.

The README currently mentions the following path: ./tests/temp/snapshotTestResult/client_postman/client.js is wrong
However, the correct path is: ./test/temp/snapshotTestResult/client_postman/client.js

Just a suggestion, happy to keep it in this PR

@Adi-204
Copy link
Member

Adi-204 commented Feb 8, 2026

@Harsh16gupta yeah the 1st one you mention is missing but just adding that won't enable clients to work and scope of issue is to solve not working clients.
The wrong path you are talking about was fixed with PR #1890 update your branch.

@Harsh16gupta
Copy link
Contributor Author

Hey maintainers

I tried Option 1 (it worked and was much simpler than Option 2), as discussed.
I’ve documented the full reasoning, the changes made, and the test output here:
https://docs.google.com/document/d/1DFdwB9S40MkFTIq5ekm8qJ7OXPHelsuc_zHmKwUZnAk/edit?usp=sharing

Please let me know if this direction makes sense or if you’d prefer a different approach.
Thanks!

@Adi-204
Copy link
Member

Adi-204 commented Feb 9, 2026

@Harsh16gupta no need to prepare docs and stuff, always just directly drop your research in github comments. Because here we don't have much options I would recommend you can proceed with your proposed solution. But remember if you are doing changes in acceptance test we need review/approval from @derberg as he introduce this testing and have much more idea/vision than me. He won't review docs, so just push your changes in this PR!

@Harsh16gupta
Copy link
Contributor Author

Thanks for the guidance, Adi!
I’ll proceed with the proposed solution directly in this PR.

@Harsh16gupta Harsh16gupta force-pushed the bug/async-await-1857-clean branch from e97ead8 to e3745d8 Compare February 9, 2026 21:43
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/templates/clients/websocket/python/components/Send.js (1)

13-27: ⚠️ Potential issue | 🟡 Minor

Correct removal of async/await — but generated docstring references the wrong library type.

The sync conversion is correct. However, Line 19 still references websockets.WebSocketCommonProtocol, which is the type from the async websockets library. Since this PR switches to the synchronous websocket-client library, the type hint in the generated docstring should reflect that (e.g., websocket.WebSocket or a more generic description).

This same stale type reference also appears in SendOperations.js (Line 36).

📝 Suggested fix
-        socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.
+        socket: The WebSocket connection to send through.
🤖 Fix all issues with AI agents
In `@packages/templates/clients/websocket/test/python/test_acceptance.py`:
- Line 6: The file test_acceptance.py has an unused import "import json"; remove
that import line from the top of the file (delete the "import json" statement)
so the test file no longer contains an unused symbol.
🧹 Nitpick comments (3)
packages/templates/clients/websocket/python/components/ReceiveOperationsDiscriminators.js (1)

4-9: JSDoc @returns is now stale — the component never returns null.

Since the early return was removed, this component always renders a <Text> element. The |null in the return type is no longer accurate.

📝 Suggested fix
- * `@returns` {React.Element|null} Rendered initialization code or null.
+ * `@returns` {React.Element} Rendered initialization code for receive operation discriminators.
packages/templates/clients/websocket/python/components/Send.js (1)

3-6: Missing JSDoc on exported Send component.

As per coding guidelines, JS functions should have JSDoc comments including parameter types and return values.

📝 Suggested JSDoc
+/**
+ * Component that generates the internal `_send` helper for the Python WebSocket client.
+ *
+ * `@param` {Object} props - Component properties.
+ * `@param` {Array<Object>} props.sendOperations - Send operations from the AsyncAPI document.
+ * `@returns` {React.Element|null} Rendered Python `_send` method or null if no send operations.
+ */
 export function Send({ sendOperations }) {
packages/templates/clients/websocket/test/python/test_acceptance.py (1)

60-83: Consider checking the return value of server_ready.wait().

server_ready.wait(timeout=5) returns False if the timeout expires before the event is set, but the return value is not checked. If the server fails to start, the test will proceed and produce a confusing failure instead of a clear startup error.

Also, regarding the static analysis hint (S104: binding to all interfaces on Line 73): this is expected in a containerized test environment where Microcks needs to reach this server.

📝 Suggested fix
-    server_ready.wait(timeout=5)
+    assert server_ready.wait(timeout=5), "WebSocket server failed to start within 5 seconds"

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/templates/clients/websocket/test/python/test_acceptance.py`:
- Around line 71-82: The server thread currently calls serve(handler, "0.0.0.0",
port) but never starts the accept loop, so update run_server to call
server.serve_forever() after creating the server (and before waiting for
test_complete) so the WebSocket server actually accepts connections; ensure you
still set server_ready.set() after server creation and keep server.shutdown()
for cleanup so server_thread (created using run_server) will block servicing
connections until test_complete.is_set().

@Harsh16gupta
Copy link
Contributor Author

Harsh16gupta commented Feb 10, 2026

Addressing CodeRabbit feedback.

@Harsh16gupta Harsh16gupta changed the title chore(python-websocket): remove async/await from websocket-client send operations chore: remove async/await from websocket-client send operations and convert the test to use synchronous library Feb 10, 2026
@Harsh16gupta
Copy link
Contributor Author

Hi maintainers, all requested changes are done. Templates are verified (screenshots attached in the PR description), and acceptance tests are also passing locally.
Happy to make any changes if needed. Thanks!

Copy link
Member

@Adi-204 Adi-204 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Harsh16gupta left few comment. In PR desc remove Dart and JS client running as we have not change anything in those, rather add screenshots of all different clients generated in python like https://github.com/asyncapi/generator/tree/master/packages/templates/clients/websocket/python#client-for-slack-with-auto-routing

It looks good, but I would recommend to drop a comment after addressing changes about how your approach in acceptance test infra works same as before.

…857-clean

Merge remote-tracking branch 'upstream/master' into bug/async-await-1857-clean
@sonarqubecloud
Copy link

@Harsh16gupta
Copy link
Contributor Author

How the Synchronous Test Approach Works the Same as Before

Same Validation Flow:

  1. Start WebSocket server
  2. Trigger Microcks test
  3. Microcks connects and validates message
  4. Poll for results

What Changed:

Aspect Old (Async) New (Sync) Why
Concurrency async/await (asyncio) threading Sync client needs sync server
Library websockets (async) websockets.sync.server Provides sync sockets
Socket Type WebSocketServerProtocol (async) ServerConnection (sync) Compatible with websocket-client
Sleep await asyncio.sleep() time.sleep() Sync equivalent
Server Lifecycle await websockets.serve() with serve() + threading Sync pattern with background execution

The Critical Improvement:

Old Version:

async def handler(websocket):
    await HoppscotchEchoWebSocketClient.send_echo_message_static(
        expected_outgoing_message, 
        websocket
    )

Incompatible with sync client

New Version:

def handler(websocket):
    HoppscotchEchoWebSocketClient.send_echo_message_static(
        expected_outgoing_message, 
        websocket
    )

Now working correctly:

  • The sync websocket (ServerConnection) is compatible with client's sync method
  • Client uses websocket-client library with sync socket interface
  • No async/sync mismatch

Threading

Old approach: Used async/await for concurrency

server = await websockets.serve(handler, port=port)
await asyncio.sleep(1)
# ... poll Microcks ...
await asyncio.sleep(2)

New approach: Uses threading for concurrency

def run_server():
    with serve(handler, "0.0.0.0", port) as server:
        server_ready.set()
        server.serve_forever()  # Blocks this thread

server_thread = threading.Thread(target=run_server, daemon=True)
server_thread.start()
# Main thread continues to poll Microcks

Both provide concurrency, just different mechanisms:

  • Async/await: Event loop manages coroutines in single thread
  • Threading: OS manages multiple threads in parallel

Result: Same validation logic, correct sync/sync compatibility. Both test client functionality, message formatting, and AsyncAPI compliance identically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

[BUG] Python Template - Async/Sync Mismatch Causes Runtime Errors

3 participants