This commit is contained in:
Jonatan Rek
2026-03-02 14:51:15 +01:00
parent f601bb3fc8
commit db0853886f
3 changed files with 84 additions and 67 deletions

View File

@@ -5,11 +5,16 @@ import docker
from time import time
_STATUS_TTL = 1.0 # seconds to cache container running-status
class DockerManager:
def __init__(self):
self._client = docker.from_env()
self._locks: dict[str, asyncio.Lock] = {}
self._idle_until: dict[str, float | None] = {}
# Cache: container_name -> (is_running, timestamp)
self._status_cache: dict[str, tuple[bool, float]] = {}
def _lock(self, name: str) -> asyncio.Lock:
if name not in self._locks:
@@ -17,22 +22,30 @@ class DockerManager:
return self._locks[name]
async def is_running(self, name: str) -> bool:
"""Return True if the container exists and is currently running."""
"""Return True if the container is running.
Result is cached for _STATUS_TTL seconds to reduce Docker API calls."""
now = time()
cached = self._status_cache.get(name)
if cached and now - cached[1] < _STATUS_TTL:
return cached[0]
loop = asyncio.get_running_loop()
try:
c = await loop.run_in_executor(None, self._client.containers.get, name)
return c.status == "running"
result = c.status == "running"
except Exception:
return False
result = False
self._status_cache[name] = (result, now)
return result
async def ensure_running(self, name: str, load_seconds: int = 0):
"""Start container if not running, then wait load_seconds."""
async with self._lock(name):
loop = asyncio.get_running_loop()
c = await loop.run_in_executor(None, self._client.containers.get, name)
if c.status != 'running':
if c.status != "running":
await loop.run_in_executor(None, c.start)
print(f"[docker] Started: {name}")
self._status_cache[name] = (True, time())
if load_seconds > 0:
await asyncio.sleep(load_seconds)
@@ -52,6 +65,7 @@ class DockerManager:
c = await loop.run_in_executor(None, self._client.containers.get, name)
await loop.run_in_executor(None, c.stop)
print(f"[docker] Stopped idle: {name}")
self._status_cache[name] = (False, time())
except Exception as e:
print(f"[docker] Failed to stop {name}: {e}")
finally: