Sample:
"""Synchronous configuration service for Azure App Configuration."""
from typing import Optional, Dict
from azure.appconfiguration import AzureAppConfigurationClient
from azure.core.exceptions import ResourceNotFoundError
class ConfigurationService:
"""Synchronous service for retrieving configuration from Azure App Configuration."""
def __init__(self, client: AzureAppConfigurationClient):
self._client = client
self._cache: Dict[str, tuple[str, str]] = {} # key -> (value, etag)
def get_setting(self, key: str, label: Optional[str] = None) -> Optional[str]:
"""
Retrieve a single setting by key and optional label.
Uses ETags to avoid re-downloading unchanged values.
Args:
key: The configuration key
label: Optional label for environment-specific values
Returns:
The configuration value or None if not found
"""
cache_key = f"{key}:{label or ''}"
etag = None
if cache_key in self._cache:
_, etag = self._cache[cache_key]
try:
config = self._client.get_configuration_setting(
key=key,
label=label,
etag=etag,
match_condition="IfNoneMatch" if etag else None
)
if config:
self._cache[cache_key] = (config.value, config.etag)
return config.value
except ResourceNotFoundError:
return None
except Exception as e:
if hasattr(e, 'status_code') and e.status_code == 304:
# Not modified, return cached value
return self._cache[cache_key][0]
raise
# Return cached value if available
if cache_key in self._cache:
return self._cache[cache_key][0]
return None
def list_settings(self, key_filter: str, label: Optional[str] = None) -> Dict[str, str]:
"""
List all settings matching a key prefix.
Args:
key_filter: Key prefix filter (e.g., "myapp:*")
label: Optional label filter
Returns:
Dictionary of key-value pairs
"""
settings = {}
for config in self._client.list_configuration_settings(
key_filter=key_filter,
label_filter=label
):
settings[config.key] = config.value
cache_key = f"{config.key}:{config.label or ''}"
self._cache[cache_key] = (config.value, config.etag)
return settings
def clear_cache(self):
"""Clear the internal cache to force a full refresh."""
self._cache.clear()
Sample: