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

Uploaded Python 3

File details

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

File metadata

File hashes

Hashes for swisper_config_service_sdk-0.1.1.tar.gz
Algorithm Hash digest
SHA256 9492b753be48c1dcd854111aaefbf09c9187d3772ac918b1b6c34cdcecf3cf24
MD5 b8bbb9c3bd4a6855f92fbb101e3d9bfd
BLAKE2b-256 6b5ad741244da46b2ec754d96372fe255ff9b1a709b5b47629d833cf92aacba8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for swisper_config_service_sdk-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7a246195fa1f1afde0cffbea282ee6f402b63691b77a4bab8007ccd8dad70c12
MD5 e7e0f0e8a8afeb615fb238f1ca002517
BLAKE2b-256 1714a4dfb829382f5893467f62770e976c0f18906552024822d6bb1816ecf09a

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