refactor: organize API routers and services into subpackages
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.
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user