Integrations¶
Extensions for deadline-budget with popular libraries.
Pydantic Settings¶
Install with: pip install deadline-budget[settings]
Configuration Classes¶
from deadline_budget.contrib.settings import BaseDeadlineSettings, OperationDeadlineConfig
# Define settings
class AppSettings(BaseModel):
deadline: BaseDeadlineSettings = Field(
default_factory=lambda: BaseDeadlineSettings(
default_budget_timeout=10.0,
default_safety_margin=0.5,
default_min_timeout=0.1,
operations={
"signup_confirm": OperationDeadlineConfig(
budget_timeout=15.0,
safety_margin=1.0,
calls_caps={
"identity_create_user": 3.0,
"credential_set_password": 3.0,
"verification_send_code": 2.0,
},
),
"login": OperationDeadlineConfig(
budget_timeout=5.0,
calls_caps={
"identity_get_user": 1.0,
"credential_verify_password": 2.0,
},
),
},
)
)
Using Configuration¶
settings = AppSettings()
# Get configuration for specific operation
config = settings.deadline.config_for_operation("signup_confirm")
# Create BudgetContext from config
ctx = BudgetContext.create(
total_seconds=config.budget_timeout,
safety_margin=config.safety_margin or settings.deadline.default_safety_margin,
min_timeout=config.min_timeout or settings.deadline.default_min_timeout,
call_caps=config.calls_caps,
)
Dishka DI Provider¶
Install with: pip install deadline-budget[dishka]
Basic Setup¶
from dishka import make_async_container
from deadline_budget.contrib.dishka import DeadlineProvider, DeadlineContextFactory
# Create container
container = make_async_container(
DeadlineProvider(),
# ... other providers
)
# Use in application
async with container() as request_container:
factory = await request_container.get(DeadlineContextFactory)
ctx = factory.create_for_operation("signup_confirm")
Custom Settings Provider¶
from dishka import Provider, Scope, provide
from deadline_budget.contrib.dishka import DeadlineSettingsProtocol
class SettingsProvider(Provider):
scope = Scope.APP
@provide
def get_deadline_settings(self, app_settings: AppSettings) -> DeadlineSettingsProtocol:
"""Provide deadline settings from app settings."""
return app_settings.deadline
# Register both providers
container = make_async_container(
SettingsProvider(),
DeadlineProvider(),
)
Using in Use Cases¶
from deadline_budget.contrib.dishka import DeadlineContextFactory
class SignupConfirmUseCase:
def __init__(
self,
uow: AsyncUnitOfWork,
deadline_factory: DeadlineContextFactory,
) -> None:
self._uow = uow
self._deadline_factory = deadline_factory
async def execute(self, email: str, password: str) -> User:
# Create budget context for this operation
ctx = self._deadline_factory.create_for_operation("signup_confirm")
async with self._uow.transaction() as tx:
user = await tx.users.create(
email=email,
timeout=ctx.timeout_for_call("identity_create_user"),
)
await tx.credentials.set_password(
user_id=user.id,
password=password,
timeout=ctx.timeout_for_call("credential_set_password"),
)
ctx.check_expired()
return user
Advanced: Operation Enums¶
from enum import Enum
class Operation(str, Enum):
SIGNUP_CONFIRM = "signup_confirm"
LOGIN = "login"
PASSWORD_RESET = "password_reset"
# Use enum with factory
ctx = deadline_factory.create_for_operation(Operation.SIGNUP_CONFIRM)
Protocol Interface¶
The Dishka provider uses protocols for flexibility:
from deadline_budget.contrib.dishka import (
DeadlineSettingsProtocol,
OperationDeadlineConfigProtocol,
)
# Implement custom settings
class CustomSettings:
@property
def default_safety_margin(self) -> float:
return 0.5
@property
def default_min_timeout(self) -> float:
return 0.1
def config_for_operation(self, operation: str) -> OperationDeadlineConfigProtocol:
# Custom logic here
...
Complete Example¶
from pydantic import BaseModel, Field
from dishka import make_async_container, Provider, Scope, provide
from deadline_budget.contrib.settings import BaseDeadlineSettings, OperationDeadlineConfig
from deadline_budget.contrib.dishka import DeadlineProvider, DeadlineContextFactory
# 1. Define settings
class AppSettings(BaseModel):
deadline: BaseDeadlineSettings = Field(
default_factory=lambda: BaseDeadlineSettings(
operations={
"signup": OperationDeadlineConfig(
budget_timeout=10.0,
calls_caps={
"identity_create": 3.0,
"credential_set": 3.0,
},
),
},
)
)
# 2. Create settings provider
class AppProvider(Provider):
scope = Scope.APP
@provide
def get_settings(self) -> AppSettings:
return AppSettings()
@provide
def get_deadline_settings(self, settings: AppSettings):
return settings.deadline
# 3. Create container
container = make_async_container(
AppProvider(),
DeadlineProvider(),
)
# 4. Use in application
async with container() as request_container:
factory = await request_container.get(DeadlineContextFactory)
ctx = factory.create_for_operation("signup")
# Use context
timeout = ctx.timeout_for_call("identity_create")
print(f"Timeout: {timeout}s")