Clawith/backend/app/services/sandbox/registry.py

84 lines
2.9 KiB
Python

"""Sandbox backend registry and factory."""
from typing import Type
from loguru import logger
from app.services.sandbox.base import SandboxBackend
from app.services.sandbox.config import SandboxConfig, SandboxType
def get_sandbox_backend(config: SandboxConfig) -> SandboxBackend:
"""
Factory function: create sandbox backend instance based on config.
This function uses dependency injection to allow easy testing and
customization. For production use, pass the config from settings.
Args:
config: SandboxConfig describing which backend to create
Returns:
SandboxBackend instance
Raises:
ValueError: If the sandbox type is unknown or not supported
"""
if not config.enabled:
raise ValueError("Sandbox is disabled")
backend_class = _BACKEND_REGISTRY.get(config.type)
if not backend_class:
raise ValueError(f"Unknown sandbox type: {config.type}")
return backend_class(config)
# Registry mapping - populated at module load time
# Using module-level dict to avoid test pollution (unlike class variables)
_BACKEND_REGISTRY: dict[SandboxType, Type[SandboxBackend]] = {}
def register_sandbox_backend(
sandbox_type: SandboxType,
backend_class: Type[SandboxBackend]
) -> None:
"""
Register a sandbox backend implementation.
This function can be used to register custom backends at runtime.
Args:
sandbox_type: The SandboxType to register
backend_class: The backend class to use for this type
"""
_BACKEND_REGISTRY[sandbox_type] = backend_class
def get_registered_backends() -> dict[SandboxType, Type[SandboxBackend]]:
"""Get all registered sandbox backends."""
return _BACKEND_REGISTRY.copy()
# Import and register built-in backends
# These are imported lazily to avoid circular imports
def _register_builtin_backends() -> None:
"""Register all built-in sandbox backends."""
from app.services.sandbox.local.subprocess_backend import SubprocessBackend
from app.services.sandbox.local.docker_backend import DockerBackend
from app.services.sandbox.api.e2b_backend import E2bBackend
from app.services.sandbox.api.judge0_backend import Judge0Backend
from app.services.sandbox.api.codesandbox_backend import CodeSandboxBackend
from app.services.sandbox.remote.self_hosted_backend import SelfHostedBackend
from app.services.sandbox.remote.aio_sandbox_backend import AioSandboxBackend
_BACKEND_REGISTRY[SandboxType.SUBPROCESS] = SubprocessBackend
_BACKEND_REGISTRY[SandboxType.DOCKER] = DockerBackend
_BACKEND_REGISTRY[SandboxType.E2B] = E2bBackend
_BACKEND_REGISTRY[SandboxType.JUDGE0] = Judge0Backend
_BACKEND_REGISTRY[SandboxType.CODEDANDBOX] = CodeSandboxBackend
_BACKEND_REGISTRY[SandboxType.SELF_HOSTED] = SelfHostedBackend
_BACKEND_REGISTRY[SandboxType.AIO_SANDBOX] = AioSandboxBackend
# Register built-in backends on module import
_register_builtin_backends()