Skip to content

Separate query and S3 read worker settings - #1103

Open
laughingman7743 wants to merge 2 commits into
masterfrom
feat/1094-separate-s3-workers
Open

laughingman7743 wants to merge 2 commits into
masterfrom
feat/1094-separate-s3-workers

Conversation

@laughingman7743

@laughingman7743 laughingman7743 commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

WHAT

Keep max_workers for the thread-pool cursor's query-result tasks and introduce s3_max_workers for S3 reads across synchronous, thread-pool, and native asyncio pandas, Polars, and Arrow cursors.
Constructor defaults and per-query overrides are independent; overrides do not change the next query's default.

Arrow keeps its native PyArrow S3 filesystem by default.
A positive s3_max_workers selects PyAthena's S3 filesystem through PyArrow's fsspec adapter for CSV and UNLOAD results; explicit None selects the native path for one query.
On the PyAthena path, Arrow timeouts merge into the connection's S3 configuration, and any dedicated client closes after eager materialization, including failures.

This is a breaking 4.0.0 cursor API change: former S3 max_workers keywords raise TypeError before query submission.
Result-set, filesystem, and upload utility max_workers arguments retain their existing meanings.
S3 workers are per file, and Polars' native Parquet concurrency remains governed by Polars.
The query-result pool does not cap active Athena queries because submission precedes queueing.
Migrate the benchmark adapters to the new cursor argument and serialize dedicated Arrow S3 client creation with the connection's existing S3 creation lock.

WHY

Closes #1094.
The previous max_workers argument had different meanings between cursor families and coupled the query pool to S3 readers in AsyncPolarsCursor.
Distinct arguments make routing consistent and allow each pool to be configured separately.

TEST

Implementation revision: 77d75ee29a65d1b9dcb4dfe8b4d7cf96502e79c3; repair revision: dec21943781fef9299786a54c032c14b7c3fd426.

  • just format and just lint: passed.
  • Offline cursor routing, override persistence, validation, real S3-file/Arrow adapter reads, and client ownership checks: 102 passed (pytest --noconftest, excluding the new AWS tests).
  • Arrow, pandas, and Polars result-set tests: 140 passed (pytest --noconftest).
  • At the repair revision, just benchmark test: 108 passed, 1 packaging test intentionally skipped; focused Arrow/S3-client checks: 11 passed (pytest --noconftest, selecting s3_workers or s3_client). Formatting and lint passed again.
  • just docs lint, just docs build, and a direct sphinx-build of this worktree: passed. The direct build has the same 214 existing diagnostics as the exact base; no new diagnostics.
  • New AWS tests cover Arrow CSV and UNLOAD reads for synchronous, thread-pool, and native asyncio cursors. They are included in the successful current-head PyAthena AWS suite.

Both self-review rounds and their repair follow-ups are complete, with records inline.
Independent review used Claude Opus 5.5, Max profile, effort high (first-party Max, not Enterprise).
Its two findings were repaired, and the bounded follow-up returned CLEAN; records and repairs are inline.
Current-head offline CI passes.
The PR is Ready, and AWS Test run 37343344427 passed at the repair revision on Python 3.14: PyAthena 3603 passed / 12 skipped; SQLAlchemy compliance and async compliance each 589 passed / 759 skipped.
All three expected AWS suites ran; the older Draft run intentionally skipped its AWS placeholder jobs.

config=connection.s3_config.merge(Config(**overrides)),
**connection._s3_client_kwargs,
)
self._s3_resources.callback(client.close)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Self-review round one — CLEAN (static behavior and implementation review).

Base: 23a54e16ecfe7cf8f64f42193d92cbb44f86cf2f
Head: 77d75ee29a65d1b9dcb4dfe8b4d7cf96502e79c3

Covered the full 30-file diff: all nine pandas/Polars/Arrow cursor constructors and execute paths, shared validation, independent query and S3 settings, repeated overrides including Arrow None, result-set and filesystem routing, Arrow CSV/UNLOAD materialization, timeout-client ownership, stream cleanup, tests, and documentation. Traced existing pandas/Polars readers, connection client configuration, the query executor, and S3File range reads and executor shutdown. Positional argument order is preserved; new parameters are keyword-only. The shared client remains connection-owned; dedicated timeout clients close on success and construction/read failure. No actionable defect found.

Evidence: local formatting/lint passed; 102 targeted offline regression cases and 140 result-set cases passed. The new AWS cases have not yet run; this static verdict does not establish live AWS behavior.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Repair review scope: base 23a54e16ecfe7cf8f64f42193d92cbb44f86cf2f, old head 77d75ee29a65d1b9dcb4dfe8b4d7cf96502e79c3, new published head dec21943781fef9299786a54c032c14b7c3fd426. Both old objects exist; range-diff confirms the original commit is unchanged and one repair commit is added. Covered all four repaired files and the affected cursor/client/result-set callers.

Round-one repair follow-up — CLEAN. The initial pass missed benchmark callers; CI and independent review identified two obsolete argument routes. Migrated pandas/Polars cursor defaults to s3_max_workers and removed thread pandas' obsolete execute override; query-pool max_workers and result-set max_workers remain correctly routed. The factory matrix and the real AsyncPandasCursor reader test exercise the migration. Protected Arrow timeout-client creation with the existing connection S3 lock; dedicated and lazy shared clients use the same lock, which is released before filesystem construction or reads. Ownership and failure cleanup remain intact. Formatting and lint passed; benchmark suite: 108 passed, 1 intentionally skipped packaging test; focused Arrow/shared-client regression checks: 11 passed. No live AWS results yet.

Comment thread docs/cursor.md
| `ArrowCursor`, `AioArrowCursor` | No query pool | `None` (native PyArrow S3 filesystem) |
| `AsyncArrowCursor` | Query task pool | `None` (native PyArrow S3 filesystem) |

Pass `s3_max_workers` to `execute()` to override the setting for one query.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Self-review round two — CLEAN (static claims, compatibility, and operational review).

Base: 23a54e16ecfe7cf8f64f42193d92cbb44f86cf2f
Head: 77d75ee29a65d1b9dcb4dfe8b4d7cf96502e79c3

Audited the PR body, changed documentation/docstrings, commit claim, and full 30-file inventory. Checked constructor defaults and positional compatibility, former S3-keyword rejection before submission, query-specific override isolation, Arrow's native default and explicit None, unchanged result-set/filesystem/upload names, per-file worker limits, Polars native Parquet routing, and query submission preceding executor queueing. Related docs and SQLAlchemy cursor selection do not introduce conflicting argument routing. No actionable finding or repair.

Traced connection sessions, filtered S3 client kwargs, botocore Config.merge, PyArrow FSSpecHandler and eager dataset reads, S3Core retry ownership, and S3File executor shutdown. Explicit timeouts preserve other connection configuration without mutation and owned-client cleanup is covered on success and failure. This change makes no AWS throughput, account-wide concurrency, or elapsed-time guarantee.

Evidence boundaries: 102 offline regression cases and 140 result-set cases passed locally. A fresh worktree Sphinx build has the same 214 diagnostics as the exact base. AWS CSV/UNLOAD and full suite validation remain pending CI; core-module changes select PyAthena (including Spark/SQLAlchemy), SQLAlchemy compliance, and async compliance suites.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Repair review scope: base 23a54e16ecfe7cf8f64f42193d92cbb44f86cf2f, old head 77d75ee29a65d1b9dcb4dfe8b4d7cf96502e79c3, new published head dec21943781fef9299786a54c032c14b7c3fd426. Both old objects exist; range-diff confirms the original commit is unchanged and one repair commit is added. Covered all four repaired files and the affected cursor/client/result-set callers.

Round-two repair follow-up — CLEAN. Checked the repair's claims against public cursor defaults, the benchmark matrix, result-set routing, Session.client concurrency, botocore configuration merge, and client lifetime. Benchmark executor_workers now explicitly supplies both pandas/Polars cursor pools while Arrow keeps its native default. The S3 creation lock serializes the new owned clients with this connection's lazy shared S3 client; this is not a global/session-wide concurrency guarantee across different connection objects. The concurrent regression uses four workers and checks ownership after creation. Existing doc/PR claims about native defaults, per-query overrides, timeout semantics, and per-file limits still hold. The initial benchmark CI failure is repaired rather than retried unchanged. Static follow-up only; AWS suites and independent repair review remain pending.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Final runtime validation: current published/reviewed head dec21943781fef9299786a54c032c14b7c3fd426; AWS Test run 37343344427 completed successfully on Python 3.14. PyAthena: 3603 passed / 12 skipped. SQLAlchemy compliance: 589 passed / 759 skipped. Async compliance: 589 passed / 759 skipped. The workflow selected the full PyAthena directory without Spark/SQLAlchemy exclusions; the six new Arrow CSV/UNLOAD cases have no skip marks or skipping fixtures and are included in that suite. CI emits aggregate results rather than per-test reports. No AWS retries or workflow changes were needed for this PR.

Current-head benchmark, source lint, docs lint/build, and license checks also pass. Earlier Draft AWS placeholder jobs are intentionally skipped and superseded by the successful Ready jobs. PR is Ready, mergeable with CLEAN merge state, and the worktree remains clean at the reviewed head. These runtime results are author validation; both independent reviews remain static. No remaining work is required for PR delivery.

Comment thread pyathena/util.py
Comment thread pyathena/arrow/result_set.py Outdated
overrides["connect_timeout"] = self._connect_timeout
if self._request_timeout is not None:
overrides["read_timeout"] = self._request_timeout
with connection._s3_client_lock:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Relayed independent repair review — CLEAN (static).
Reviewer: Claude Code; requested and verified claude-opus-5-5, profile max, effort high; first-party Claude Max, not Enterprise. Authentication was rechecked with API key/token/provider overrides removed.
Session: b295234f-5bd8-4d9c-a178-0864072a9340.
Old/new base: 23a54e16ecfe7cf8f64f42193d92cbb44f86cf2f
Old reviewed head: 77d75ee29a65d1b9dcb4dfe8b4d7cf96502e79c3
New reviewed/published head: dec21943781fef9299786a54c032c14b7c3fd426

Read the full four-file repair diff and patch-series comparison, with API context from the full diff. Traced all pandas/Polars constructor/execute routes, independent pools, benchmark factory/matrix/reader tests and README, unchanged result-set arguments, Arrow native defaults, connection locking/configuration, owned/shared client lifetime, thread-pool and aio callers, and the concurrent regression. No introduced defect found. The benchmark routing is corrected and the S3 lock is released before reads without recursive acquisition.

Invocation retained Read/Grep/Glob only, with safe/restricted mode and hooks/skills/MCP/memory/commands/network/GitHub disabled. Snapshot hash manifest is unchanged, and the PR worktree remains clean at the reviewed head.

Reviewer notes (not defects): the existing connection comment describes shared-client lazy initialization, rather than the additional lock use; the regression's locked() assertion does not prove which thread owns a lock. Author assessment: the shared-client comment remains accurate, and the test detects omission of the dedicated-client guard while source inspection establishes mutual exclusion. No repair is required for these notes. The reviewer also identified existing Session factories using other/no locks (Glue/to_sql), predating this PR; those are outside this change and no session-wide guarantee is claimed.

Limits: static inspection only; no tests, builds, type checks, benchmarks, or live AWS execution by the reviewer; thread interleavings and dependency runtime behavior were not measured. The rest of the original diff was not re-reviewed in this bounded follow-up; its completed initial review is recorded above. Author local checks and current-head offline CI pass; AWS CI remains pending serialized execution.

@laughingman7743
laughingman7743 marked this pull request as ready for review October 5, 2026 16:46

This branch has not been deployed

No deployments
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.

Separate the two meanings of max_workers in the cursors

1 participant