37ccaa4fdc
Service organization (19 files moved into 6 subpackages): - services/instance/ — event_bus, health_monitor, lifecycle_hooks - services/config/ — config_profile_resolver - services/git/ — clone, git_operations, git_service - services/build/ — docker_build, manifest_compiler - services/terminal/ — terminal_manager, terminal_session - services/shared/ — correlation, file_service, notification_service, permission_fixer, readiness_probe, ssh_keys, tunnel, workspace_manager API router organization (16 files moved into 6 subpackages): - api/tool/ — tool_instances, tool_types, tool_definitions, tool_types_validation, sessions (extracted from tool_instances) - api/config/ — config_profiles, user_config - api/workspace/ — workspaces, workspace_files, workspace_git, workspace_instances - api/user/ — users, auth, ssh_keys - api/project/ — projects, git_repositories - api/system/ — health, events, notifications, dashboard, terminal, instance_proxy Updated main.py imports and all __init__.py re-exports. Sessions router extracted from tool_instances.py into api/tool/sessions.py. Quality gates: py_compile passed, ruff passed.
67 lines
2.1 KiB
Python
67 lines
2.1 KiB
Python
"""Readiness probe service for checking if containers are ready."""
|
|
|
|
import asyncio
|
|
import logging
|
|
import subprocess
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
async def execute_probe(
|
|
container_id: str,
|
|
command: str,
|
|
timeout: int = 30,
|
|
interval: int = 2,
|
|
) -> tuple[bool, list[str]]:
|
|
"""Execute a readiness probe command inside a container.
|
|
|
|
Args:
|
|
container_id: Docker container ID or name
|
|
command: Command to execute inside the container
|
|
timeout: Maximum total time to wait (seconds)
|
|
interval: Time between retries (seconds)
|
|
|
|
Returns:
|
|
Tuple of (success, logs)
|
|
"""
|
|
logs = []
|
|
start_time = asyncio.get_event_loop().time()
|
|
attempt = 0
|
|
|
|
while True:
|
|
attempt += 1
|
|
elapsed = asyncio.get_event_loop().time() - start_time
|
|
|
|
if elapsed >= timeout:
|
|
logs.append(f"Probe timed out after {timeout}s ({attempt} attempts)")
|
|
return False, logs
|
|
|
|
try:
|
|
logger.debug("Probe attempt %d: %s", attempt, command)
|
|
|
|
# Execute command inside container
|
|
result = subprocess.run(
|
|
["docker", "exec", container_id, "sh", "-c", command],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=interval, # Each attempt has its own timeout
|
|
)
|
|
|
|
if result.returncode == 0:
|
|
logs.append(f"Attempt {attempt}: Success")
|
|
if result.stdout:
|
|
logs.append(f"Output: {result.stdout.strip()}")
|
|
return True, logs
|
|
else:
|
|
logs.append(f"Attempt {attempt}: Failed (exit code {result.returncode})")
|
|
if result.stderr:
|
|
logs.append(f"Stderr: {result.stderr.strip()[:200]}")
|
|
|
|
except subprocess.TimeoutExpired:
|
|
logs.append(f"Attempt {attempt}: Command timed out")
|
|
except Exception as exc:
|
|
logs.append(f"Attempt {attempt}: Error - {exc}")
|
|
|
|
# Wait before next attempt
|
|
await asyncio.sleep(interval)
|