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.0.tar.gz (12.5 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.0-py3-none-any.whl (12.5 kB view details)

Uploaded Python 3

File details

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

File metadata

File hashes

Hashes for swisper_config_service_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6d4e6650f37b47275b790be6b68b7e732024dba98c9e530f99076c6b39fd35bc
MD5 631a4046e101915a6d9fc24a34a22849
BLAKE2b-256 9fdddf47e1fe95940b13753db5bb4e8c1de0ba10e832646c9e54652ae0040cad

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for swisper_config_service_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0e7a4677de9f66711b8cca2a39383f853cdec5e45ee031794c6745ffe1c627b2
MD5 165105ed56b288e42e795061eae58078
BLAKE2b-256 5762cc68d1c408bfd24ba4cd4029abacac56ad9c9b78d1ad08ef77ba7e6f17fc

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