Async and Sync Clients
Relevant source files
The following files were used as context for generating this wiki page:
The Infrahub Python SDK provides two primary interfaces for interacting with infrastructure data: InfrahubClient (asynchronous) and InfrahubClientSync (synchronous). These clients abstract the Infrahub API, allowing developers to work with native Python objects. Every public feature in the SDK must ship on both clients with matching method names, signatures, and behaviors to ensure dual API parity.
Sources: dev/constitution.md:21-26, AGENTS.md:31-35, infrahub_sdk/client.py
Core Architecture and Parity
The SDK follows a strict "Async/Sync Dual API Parity" principle. This non-negotiable requirement ensures that functionality remains consistent across both programming models. Internal logic, API interaction, and data transformation reside within the SDK core, while specific clients act as interfaces for different concurrency needs.
Inheritance and Structure
Both client types derive shared logic from internal base implementations. This structure minimizes code duplication while enforcing behavioral consistency.
The diagram shows the relationship between the base internal client and the two public-facing client implementations.
Sources: dev/constitution.md:21-27, infrahub_sdk/client.py, dev/specs/ihs-259-sdk-x-priority-header/tasks.md:65-68
Feature Parity Enforcement
Parity is strictly enforced through automated testing. The suite validates that method counts and signatures match between InfrahubClient and InfrahubClientSync.
- Validation Methods:
test_validate_method_signatureandtest_method_count. - Parity Fixtures: Tests use a
BothClientsfixture to execute assertions against both the async and sync paths.
Sources: dev/constitution.md:30-32, dev/specs/ihs-259-sdk-x-priority-header/tasks.md:24-25
Key Features and Components
The clients share a common set of capabilities designed for infrastructure management.
| Feature | Description | Relevant Client Methods |
|---|---|---|
| Object Retrieval | Fetches single nodes or filtered lists of nodes. | get(), all(), filters() |
| Data Creation | Instantiates new infrastructure nodes. | create() |
| GraphQL Execution | Executes raw GraphQL queries or mutations. | execute_graphql(), _execute_graphql_with_file() |
| Rate Limiting | Automatically retries requests on HTTP 429 responses with jittered backoff. | _send_with_rate_limit_retry() |
| Request Priority | Injects an X-Priority header for server-side task prioritization. | __init__(priority=...), execute_graphql(priority=...) |
Sources: tasks.py:34-40, dev/specs/ihs-249-sdk-429-retry/tasks.md:58-75, dev/specs/ihs-259-sdk-x-priority-header/tasks.md:72-105
Request Handling and Middlewares
The clients manage common request concerns such as authentication headers, tracking, and rate limiting.
Rate Limit Retry Logic
The clients implement a retry mechanism for 429 Too Many Requests responses. This logic is shared but implemented using model-specific sleep functions (asyncio.sleep for async, time.sleep for sync).
This flowchart illustrates the request retry loop used by both clients to handle server-side rate limiting.
Sources: dev/specs/ihs-249-sdk-429-retry/tasks.md:58-75
Header Injection
Clients handle automatic header injection for every request. This includes:
- Authentication:
X-INFRAHUB-KEYis injected during initialization. - Tracking:
X-Infrahub-Trackerheaders are added to track requests. - Priority:
X-Priorityheaders are injected based on client configuration or per-request overrides.
Sources: dev/specs/ihs-259-sdk-x-priority-header/tasks.md:20-22, 65-68
Usage Examples
Async Client Usage
The InfrahubClient is used within async functions and requires the await keyword for network operations.
client = InfrahubClient()
node = await client.get(kind="NetworkDevice", identifier="device-01")
await node.save()
Sources: AGENTS.md:33-37
Sync Client Usage
The InfrahubClientSync provides a traditional blocking interface suitable for scripts and simple automation tasks.
client = InfrahubClientSync()
node = client.get(kind="NetworkDevice", identifier="device-01")
node.save()
Sources: AGENTS.md:33-37
Summary
The dual-client architecture of the Infrahub Python SDK ensures that all developers, regardless of their chosen concurrency model, have access to a stable and consistent API. By strictly maintaining parity between InfrahubClient and InfrahubClientSync, the project avoids breaking changes for sync consumers while providing modern async capabilities for high-performance applications.