Skip to content

feat(py-client): Implement "many" api for batch requests - #546

Open
matt-codecov wants to merge 1 commit into
mainfrom
matt/py-client-many
Open

feat(py-client): Implement "many" api for batch requests#546
matt-codecov wants to merge 1 commit into
mainfrom
matt/py-client-many

Conversation

@matt-codecov

@matt-codecov matt-codecov commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

#277 / #478 implemented the many API in the Rust client which uses Objectstore's batch endpoint. This PR ports it over to Python.

Incorporates direction from #419.

Closes FS-330

Some notes:

  • Hand-rolls the max concurrency limit rather than rely on ThreadPoolExecutor's max_workers to allow for results to be streamed from individual batch requests without having to buffer the whole response. Otherwise a batch of 1000 5MB GET results would eat 5GB RAM and delay yielding anything to the caller.
  • Kind of aggressive about raising errors. Being flexible is the server's job, not the client's.
  • There's duplicated code. The Get / Put operation type classes copy the arg list of the get() and put() methods on session, the decompression code in get() is copied... but I didn't want to touch existing code much to reorganize in this PR.
  • Default concurrency is 1 because that's the default urllib3 connection pool size. You can still send concurrent requests with a connection pool size of 1, it just opens/closes a connection per request and logs a warning about it instead of actually pooling.
  • Actually reads the "part number" header from the batch endpoint response. Each operation's response is tagged with the operation's index in the input list so you can figure out which keyless PUT was assigned which key.
  • Robot generated the tests, haven't reviewed them yet.

@linear-code

linear-code Bot commented Jul 8, 2026

Copy link
Copy Markdown

FS-361

FS-330

@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.77049% with 38 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.36%. Comparing base (d5d3a65) to head (9b05797).

Files with missing lines Patch % Lines
clients/python/src/objectstore_client/many.py 92.29% 37 Missing ⚠️
clients/python/src/objectstore_client/client.py 90.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #546      +/-   ##
==========================================
+ Coverage   89.22%   89.36%   +0.13%     
==========================================
  Files         109      111       +2     
  Lines       19089    19688     +599     
==========================================
+ Hits        17033    17595     +562     
- Misses       2056     2093      +37     
Components Coverage Δ
Rust Backend 92.93% <ø> (ø)
Rust Client 81.97% <ø> (ø)
Python Client 93.68% <93.77%> (+0.11%) ⬆️

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jan-auer

jan-auer commented Jul 9, 2026

Copy link
Copy Markdown
Member

Please see also the now closed #419. It's gone out of sync with main, so it's better to carry on here.

The prior PR focused on streaming as much as possible and had gone through a round of feedback with the Python SDK maintainers for the public API. Also, there's configuration for concurrency that uses an optional thread pool executor. I hope there are some parts we could leverage from that.

@matt-codecov

Copy link
Copy Markdown
Contributor Author

bugbot run
@sentry review

Comment thread clients/python/src/objectstore_client/many.py Outdated
Comment thread clients/python/src/objectstore_client/many.py Outdated
Comment thread clients/python/src/objectstore_client/many.py Outdated
@matt-codecov
matt-codecov marked this pull request as ready for review August 25, 2026 03:00
@matt-codecov
matt-codecov requested a review from a team as a code owner August 25, 2026 03:00
Comment thread clients/python/src/objectstore_client/client.py Outdated
Comment thread clients/python/src/objectstore_client/many.py Outdated
Comment thread clients/python/README.md Outdated
@lcian lcian changed the title feat(py-client): implement "many" api for batch requests feat(py-client): Implement "many" api for batch requests Aug 25, 2026
Comment thread clients/python/src/objectstore_client/client.py Outdated
Comment thread clients/python/src/objectstore_client/many.py Outdated
Comment thread clients/python/src/objectstore_client/many.py Outdated

A port of the ``ZSTD_COMPRESSBOUND`` macro definition in ``zstd.h``.
"""
margin = ((128 << 10) - size) >> 11 if size < (128 << 10) else 0

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I assume this is correct.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

https://github.com/facebook/zstd/blob/82d322c4973d9e2968d94047a40892bc6d9a9bdf/lib/zstd.h#L249 is the source. it is a bit of a mess to parse but here it is with some extra indentation for clarity:

#define ZSTD_COMPRESSBOUND(srcSize) \
  ( \
    ((size_t)(srcSize) >= ZSTD_MAX_INPUT_SIZE) \
      ? 0 \
      : (srcSize) + ((srcSize)>>8) + (         /* size + (size >> 8) +             */ \
        ((srcSize) < (128<<10))                /* if size < (128 << 10)            */ \
          ? (((128<<10) - (srcSize)) >> 11)    /* then ((128 << 10) - size) >> 11  */ \
          : 0                                  /* else 0                           */ \
      ) \
  )

once upon a time writing convoluted preprocessor macros was my job

Comment thread clients/python/src/objectstore_client/many.py Outdated
Comment on lines +466 to +470
if concurrency == 1 and executor is None:
for item in work:
yield from _run_work(session, item)
else:
yield from _execute_concurrent(session, work, concurrency, executor)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we really need the special case for concurrency=1 or could we just send the ops into _execute_concurrent with a special/single-threaded executor and that's it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

the special case here skips any executor/threading and just runs it on the caller thread. i don't think there is a "same thread executor" ready-made we could use here. but it probably wouldn't be hard to write

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i left this as-is

Comment thread clients/python/src/objectstore_client/many.py Outdated
Comment thread clients/python/src/objectstore_client/many.py
Comment thread clients/python/src/objectstore_client/many.py Outdated
Comment thread clients/python/src/objectstore_client/many.py
Comment thread clients/python/src/objectstore_client/formdata.py

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ff03dcd. Configure here.

Comment thread clients/python/src/objectstore_client/many.py Outdated
Comment thread clients/python/src/objectstore_client/many.py Outdated
Comment thread clients/python/src/objectstore_client/many.py Outdated
@lcian
lcian self-requested a review September 4, 2026 11:43
Comment thread clients/python/src/objectstore_client/many.py Outdated
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.

3 participants