Skip to content

fix(http): ApiClient.request_sync must not wrap sync result in event loop - #1367

Open
Harsh23Kashyap wants to merge 2 commits into
qdrant:masterfrom
Harsh23Kashyap:fix/api-client-request-sync
Open

fix(http): ApiClient.request_sync must not wrap sync result in event loop#1367
Harsh23Kashyap wants to merge 2 commits into
qdrant:masterfrom
Harsh23Kashyap:fix/api-client-request-sync

Conversation

@Harsh23Kashyap

Copy link
Copy Markdown

Fixes #1336

Problem

ApiClient.request_sync is a synchronous convenience wrapper, but it shared its body with AsyncApiClient.request_sync — both called get_event_loop().run_until_complete(self.request(...)). For the async class that's correct (self.request returns a coroutine). For the sync class, self.request returns an ordinary value, so every successful response raised TypeError: An asyncio.Future, a coroutine or an awaitable is required instead of being returned.

Repro from the issue:

client = ApiClient("http://localhost:6333")
with patch.object(client, "request", return_value={"ok": True}):
    client.request_sync(type_=dict, method="GET", url="/collections")
# TypeError: An asyncio.Future, a coroutine or an awaitable is required

Fix

qdrant_client/http/api_client.pyApiClient.request_sync now returns self.request(...) directly. The async side (AsyncApiClient.request_sync) is unchanged — it still uses run_until_complete because its self.request is a coroutine.

One-line change, 1 line of context.

Test

tests/test_qdrant_client.py::test_api_client_request_sync_returns_value — pure unit regression that patches ApiClient.request to return a plain dict and asserts the dict flows through. Also covers the type_=None path. Fails on master (TypeError), passes with the fix. No live server required.

Scope

  • 1 production change (1 line replaced in ApiClient.request_sync)
  • 1 new test (~30 lines)
  • 1 import added (from unittest.mock import patch)

No API changes (the wrapper is request_sync and its signature is unchanged), no behavior change for the existing happy path, no dependency change. Distinct from the previous #1326/#1366 async-side timeout fix.

…loop

The sync ApiClient.request_sync shared the same body as the async
AsyncApiClient.request_sync: it called get_event_loop().run_until_complete
on self.request(...). For the async client, self.request returns a
coroutine, so the event-loop bridge is correct. For the sync client,
self.request returns an ordinary value, so run_until_complete raised
TypeError: An asyncio.Future, a coroutine or an awaitable is required
on every successful response.

The two methods live in the same file and were clearly meant to differ
in exactly this respect. The async side stays unchanged; the sync side
now just returns self.request(...) directly.

Adds a unit regression that mocks request with a plain dict and asserts
the dict is returned, plus a type_=None path check. No live server
required.

Fixes qdrant#1336
@netlify

netlify Bot commented Aug 21, 2026

Copy link
Copy Markdown

Deploy Preview for poetic-froyo-8baba7 ready!

Name Link
🔨 Latest commit b94e923
🔍 Latest deploy log https://app.netlify.com/projects/poetic-froyo-8baba7/deploys/6a88b9c7b3ffac0008933442
😎 Deploy Preview https://deploy-preview-1367--poetic-froyo-8baba7.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d82dcdf9-fafb-4d38-9051-a2438f5af419

📥 Commits

Reviewing files that changed from the base of the PR and between 228f4ba and b94e923.

📒 Files selected for processing (1)
  • tests/test_qdrant_client.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_qdrant_client.py

Included review availability: Your plan provides up to 4 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

ApiClient.request_sync now directly returns the result of self.request, without passing it to the event loop. Tests mock the request method and verify dictionary and None responses, along with forwarded request arguments.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to b94e9

The synchronous request wrapper now returns its synchronous result directly, restoring the documented behavior without changing its API or the asynchronous path. No actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary fix to ApiClient.request_sync.
Description check ✅ Passed The description explains the defect, fix, regression test, and scope, all of which match the changeset.
Linked Issues check ✅ Passed The changes satisfy issue #1336 by fixing the sync wrapper, preserving async behavior, and adding typed and None response coverage.
Out of Scope Changes check ✅ Passed The production change and regression test are directly related to issue #1336, with no unrelated scope identified.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

The 3-line regression comment for qdrant#1336 repeated the bug description
that the linked issue already has. Replaced with a 2-line version that
points to the bug number and the operation that was wrong. Also dropped
the inline comment on the type_=None test block — the block's patch and
assertion are self-evident.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ApiClient.request_sync rejects successful synchronous responses as non-awaitable

1 participant