Skip to main content

Python SDK for the Config Service API - centralized configuration management with hierarchical overrides

Project description

Swisper Config Service SDK

Python SDK for the Config Service API - centralized configuration management with hierarchical overrides.

Installation

pip install swisper-config-service-sdk

Or install from source:

pip install ./backend/config-service/sdk

Quick Start

from swisper_config_service_sdk import ConfigServiceClient

async with ConfigServiceClient() as client:
    # Get a configuration value
    config = await client.get("feature-flag")
    print(f"Value: {config.value}")

    # Get with default fallback
    value = await client.get_value("timeout", default="30")

    # Create or update a configuration
    await client.upsert("my-config", "my-value")

Hierarchical Configuration

The Config Service supports three levels of configuration:

  1. Global (base) - Default configuration for all agents/nodes
  2. Agent-level - Override for a specific agent
  3. Node-level - Override for a specific node within an agent

When retrieving a configuration, the service uses fallback: node → agent → global.

async with ConfigServiceClient() as client:
    # Get global config
    global_config = await client.get("feature-flag")

    # Get agent-specific config (falls back to global if not set)
    agent_config = await client.get("feature-flag", agent_id="agent-123")

    # Get node-specific config (falls back to agent, then global)
    node_config = await client.get(
        "feature-flag",
        agent_id="agent-123",
        node_id="node-456"
    )

    # Check where the value came from
    print(f"Source: {node_config.source}")  # "base", "agent", "node", or "cache"

Configuration

Environment Variables

Variable Default Description
CONFIG_SERVICE_URL http://localhost:8090 Base URL of the Config Service
CONFIG_SERVICE_TIMEOUT 30.0 Request timeout in seconds
CONFIG_SERVICE_CONNECT_TIMEOUT 5.0 Connection timeout in seconds
CONFIG_SERVICE_MAX_RETRIES 3 Max retry attempts for transient failures

Programmatic Configuration

from swisper_config_service_sdk import ConfigServiceClient, ConfigServiceSettings

settings = ConfigServiceSettings(
    url="http://config-service.internal:8090",
    timeout=60.0,
    max_retries=5,
)

async with ConfigServiceClient(settings=settings) as client:
    ...

API Reference

ConfigServiceClient

get(name, *, agent_id=None, node_id=None) -> ConfigurationWithSource

Get a configuration by name with hierarchical fallback.

config = await client.get("feature-flag", agent_id="agent-1")
print(config.value)   # The configuration value
print(config.source)  # Where it came from: "base", "agent", "node", "cache"

get_value(name, *, agent_id=None, node_id=None, default=None) -> str | None

Convenience method to get just the value with a default.

value = await client.get_value("timeout", default="30")

upsert(name, value, *, agent_id=None, node_id=None) -> ConfigurationItem

Create or update a configuration.

# Global config
await client.upsert("feature-flag", "enabled")

# Agent-level override
await client.upsert("feature-flag", "disabled", agent_id="agent-1")

# Node-level override
await client.upsert("feature-flag", "beta", agent_id="agent-1", node_id="node-1")

list(*, skip=0, limit=100, agent_id=None, node_id=None) -> list[ConfigurationItem]

List configurations with optional filtering.

# List all configs
configs = await client.list()

# List agent-specific configs
agent_configs = await client.list(agent_id="agent-1")

delete(name) -> bool

Delete a configuration and all its overrides.

await client.delete("old-config")

health() -> HealthStatus

Check service liveness.

status = await client.health()
print(status.status)  # "ok"

ready() -> ReadyStatus

Check service readiness (includes dependency checks).

status = await client.ready()
print(status.redis)  # "connected" or "disconnected"

is_healthy() -> bool

Quick health check returning boolean.

if await client.is_healthy():
    print("Service is healthy")

Error Handling

from swisper_config_service_sdk import (
    ConfigServiceClient,
    ConfigNotFoundError,
    ConfigValidationError,
    ConfigServiceUnavailableError,
    ConfigServiceTimeoutError,
)

async with ConfigServiceClient() as client:
    try:
        config = await client.get("my-config")
    except ConfigNotFoundError as e:
        print(f"Config '{e.name}' not found")
    except ConfigValidationError as e:
        print(f"Invalid request: {e.detail}")
    except ConfigServiceTimeoutError:
        print("Request timed out")
    except ConfigServiceUnavailableError as e:
        print(f"Service unavailable: {e}")

FastAPI Integration

For FastAPI applications, you can use the shared client pattern:

from contextlib import asynccontextmanager
from fastapi import FastAPI, Depends
from typing import Annotated

from swisper_config_service_sdk import (
    ConfigServiceClient,
    connect_shared_client,
    close_shared_client,
    get_shared_client,
)

@asynccontextmanager
async def lifespan(app: FastAPI):
    await connect_shared_client()
    yield
    await close_shared_client()

app = FastAPI(lifespan=lifespan)

async def get_config_client() -> ConfigServiceClient:
    return await get_shared_client()

ConfigClientDep = Annotated[ConfigServiceClient, Depends(get_config_client)]

@app.get("/feature/{name}")
async def get_feature(name: str, client: ConfigClientDep):
    value = await client.get_value(name, default="disabled")
    return {"feature": name, "value": value}

Development

Install dev dependencies

pip install -e ".[dev]"

Run tests

pytest

Run linting

ruff check .
mypy .

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

swisper_config_service_sdk-0.1.6.tar.gz (15.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

swisper_config_service_sdk-0.1.6-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

Details for the file swisper_config_service_sdk-0.1.6.tar.gz.

File metadata

File hashes

Hashes for swisper_config_service_sdk-0.1.6.tar.gz
Algorithm Hash digest
SHA256 99611533e96731bcbabd80a70a95f63e5567966f59bfbf080e890388e3501860
MD5 cf7db9bc89c89ef901f778cc22d65b80
BLAKE2b-256 7e11e50dd328edf8ea5dd17b9fcbdd8f6037c461e8653e811f891a04d0379670

See more details on using hashes here.

File details

Details for the file swisper_config_service_sdk-0.1.6-py3-none-any.whl.

File metadata

File hashes

Hashes for swisper_config_service_sdk-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 1a7db13da3401ce1f51b4b737e5230d9ae25772a9b4da3ed99cb8755f046547b
MD5 10ff481a5937263bf45a832aa840be97
BLAKE2b-256 90e8563c62e806595c90064b0db4b73c5d0dff35d0f7dd71d48c790e7c4f91a5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page