Skip to content

perf: shared HTTP client and latency optimizations#14

Open
gregnazario wants to merge 4 commits intomainfrom
perf/shared-http-client-and-latency-optimizations
Open

perf: shared HTTP client and latency optimizations#14
gregnazario wants to merge 4 commits intomainfrom
perf/shared-http-client-and-latency-optimizations

Conversation

@gregnazario
Copy link
Copy Markdown
Collaborator

Summary

  • Shared HTTP client: Eliminates per-request httpx client creation across the entire SDK. Previously, each API call (gas estimation, simulation, submission, confirmation polling) created and destroyed its own TCP+TLS connection — up to 5 per transaction. Now a single pooled client with keep-alive handles all requests, saving ~200-1500ms per transaction flow.
  • Faster confirmation polling: Changed from fixed 1s interval to escalating delays (200ms → 200ms → 500ms → 500ms → 1s), shaving up to 800ms off fast-confirming transactions.
  • Request timeouts: Added 5s timeouts to gas price estimation, order status queries, and confirmation polling that previously had no timeout at all.
  • Lifecycle management: BaseSDK, BaseSDKSync, and DecibelReadDex now support close() and context managers (async with / with) for proper connection pool cleanup.

Files changed

File Changes
_constants.py Added HTTP_LIMITS and HTTP_TIMEOUT shared config
_base.py Shared client on both async/sync base classes, escalating poll delays, close/context manager
_gas_price_manager.py Optional shared client + 5s timeouts
_order_status.py Optional shared client + 5s timeouts
read/_base.py http_client fields on ReaderDeps, wired to all reader methods
read/__init__.py DecibelReadDex creates shared client, close/context manager
write/__init__.py Pass shared client to OrderStatusClient

Test plan

  • All 48 existing tests pass (pytest tests/)
  • Ruff linting clean (ruff check src/)
  • No new pyright errors introduced
  • Manual verification: run example against testnet to confirm latency improvement

Eliminate per-request httpx client creation across the SDK, reducing
TCP/TLS handshake overhead from 3-5 connections per transaction flow
to zero (via connection pooling and keep-alive).

- Add shared httpx.AsyncClient/Client to BaseSDK, BaseSDKSync, and
  DecibelReadDex with configurable connection pool limits
- Wire shared client through fee payer submission, gas price manager,
  order status client, and all reader endpoints
- Add close()/context manager support for proper client lifecycle
- Use escalating poll intervals (200ms→500ms→1s) for faster tx
  confirmation on quick-confirming transactions
- Add 5s timeouts to gas price estimation, simulation, order status,
  and confirmation polling to prevent indefinite hangs
Copilot AI review requested due to automatic review settings April 14, 2026 01:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves SDK latency and reliability by reusing pooled httpx clients across request flows, adding lifecycle management (close/context managers), tightening request timeouts, and optimizing transaction confirmation polling.

Changes:

  • Introduces shared httpx client configuration (HTTP_LIMITS, HTTP_TIMEOUT) and wires shared clients through read/write SDK paths.
  • Adds close() + context manager support for async/sync SDK entrypoints and updates request codepaths to reuse the shared client.
  • Optimizes confirmation polling by using escalating delays and adds explicit 5s timeouts to selected network calls.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/decibel/_constants.py Adds shared httpx limits/timeout constants for pooled clients.
src/decibel/_base.py Uses shared client for core write flow + adds close/context manager + faster polling delays.
src/decibel/_gas_price_manager.py Adds optional injected clients and explicit 5s timeouts for gas estimation.
src/decibel/_order_status.py Adds optional injected clients and explicit 5s timeouts for order status queries.
src/decibel/read/_base.py Threads optional shared clients through reader request helpers.
src/decibel/read/__init__.py Creates shared async client for readers and adds close/context manager.
src/decibel/write/__init__.py Passes shared base client into OrderStatusClient (async/sync).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Add 749 new tests (797 total) covering all SDK modules with mocked
HTTP clients and blockchain interactions.

Test files added:
- test_utils_extended.py — FetchError, request functions, address derivation
- test_base.py — BaseSDK/BaseSDKSync lifecycle, tx flow, polling
- test_fee_pay.py — fee payer submission routing and serialization
- test_transaction_builder.py — BCS encoding, type parsing, tx building
- test_gas_price_manager.py — async/sync gas price caching
- test_order_status.py — order status queries and parsing
- test_exceptions.py — custom exception classes
- test_pagination.py — query param construction
- read/test_base_reader.py — BaseReader HTTP delegation
- read/test_readers.py — all 22 reader modules
- read/test_ws.py — WebSocket subscription management
- write/test_write_dex.py — all write operations (async + sync)
- test_admin.py — all admin operations (async + sync)

Coverage: 25% → 95% (3411/3592 statements covered)
- Add explicit timeout=5.0 to gas price estimation in both async and
  sync BaseSDK (was relying on shared client default of 10s)
- Close WebSocket subscription in DecibelReadDex.close() to prevent
  leaking background receive tasks and open sockets
- Apply ruff formatting fixes
Copilot AI review requested due to automatic review settings April 14, 2026 02:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 22 out of 24 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Add try/except for ConnectTimeout/ReadTimeout/ConnectError in sync
  _wait_for_transaction to match async behavior and prevent raw httpx
  exceptions from aborting confirmation polling
- Simplify admin.usdc_balance to use shared client directly (no longer
  nullable after shared client changes)
- Remove unused httpx import from admin.py
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 23 out of 25 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 23 out of 25 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Collaborator

@WGB5445 WGB5445 left a comment

Choose a reason for hiding this comment

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

DecibelReadDex.close() cleanup is not robust enough.
In read/init.py, await self.ws.close() is called before await self._http_client.aclose(). If the former raises an exception, the latter may not be executed.

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