mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-17 18:25:42 +02:00
55 lines
1.9 KiB
Python
55 lines
1.9 KiB
Python
"""Agent self-restart handshake: a workspace's restart.sh touches
|
|
.openswarm/restart-requested and the AppRuntimeManager watcher consumes it and
|
|
restarts every attached instance of that workspace. This is the only restart
|
|
path an agent has (no API token, uvicorn runs without --reload), so pin both
|
|
the pickup and the sentinel consumption restart.sh's wait loop depends on."""
|
|
|
|
import asyncio
|
|
import os
|
|
|
|
import pytest
|
|
|
|
from backend.apps.outputs import runtime as runtime_mod
|
|
from backend.apps.outputs.runtime import AppRuntime, AppRuntimeManager
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_sentinel_restarts_all_attached_instances(tmp_path, monkeypatch):
|
|
monkeypatch.setattr(runtime_mod, "RESTART_SENTINEL_POLL_SECONDS", 0.05)
|
|
restarted: list[int] = []
|
|
|
|
async def p_fake_start(self):
|
|
return True
|
|
|
|
async def p_fake_restart(self):
|
|
restarted.append(self.instance)
|
|
return True
|
|
monkeypatch.setattr(AppRuntime, "start", p_fake_start)
|
|
monkeypatch.setattr(AppRuntime, "restart", p_fake_restart)
|
|
# The stub spawns no process; the watcher only restarts live runtimes, so fake liveness.
|
|
monkeypatch.setattr(AppRuntime, "running", property(lambda self: True))
|
|
|
|
mgr = AppRuntimeManager()
|
|
ws = str(tmp_path)
|
|
await mgr.attach("ws1", ws, 1)
|
|
await mgr.attach("ws1", ws, 2)
|
|
|
|
os.makedirs(os.path.join(ws, ".openswarm"), exist_ok=True)
|
|
sentinel = os.path.join(ws, ".openswarm", "restart-requested")
|
|
with open(sentinel, "w", encoding="utf-8") as f:
|
|
f.write("")
|
|
|
|
for _ in range(100):
|
|
await asyncio.sleep(0.05)
|
|
if len(restarted) >= 2:
|
|
break
|
|
# Sentinel consumed (restart.sh's wait loop unblocks) and BOTH instances bounced.
|
|
assert not os.path.exists(sentinel)
|
|
assert sorted(restarted) == [1, 2]
|
|
|
|
# No sentinel -> no further restarts.
|
|
await asyncio.sleep(0.2)
|
|
assert sorted(restarted) == [1, 2]
|
|
if mgr.restart_watch_task:
|
|
mgr.restart_watch_task.cancel()
|