mirror of
https://github.com/ArchiveBox/ArchiveBox.git
synced 2026-09-12 19:50:57 +05:00
Avoid restarting OpenCode on transient health misses
This commit is contained in:
parent
3327edba24
commit
7f1767a2db
@ -37,6 +37,7 @@ _PROCESS: subprocess.Popen | None = None
|
||||
_PROCESS_LOCK = threading.Lock()
|
||||
_SESSION_LOCK = threading.Lock()
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_PROCESS_HEALTH_GRACE = 5
|
||||
_PROXY_PREFIX = "/admin/agent/opencode"
|
||||
_PROXY_PREFIX_REGEX = _PROXY_PREFIX.replace("/", r"\/")
|
||||
_PROXY_PREFIX_NO_SLASH_REGEX = _PROXY_PREFIX.lstrip("/").replace("/", r"\/")
|
||||
@ -401,6 +402,11 @@ def _ensure_opencode(settings: dict) -> tuple[bool, str]:
|
||||
if _health(settings):
|
||||
return True, ""
|
||||
if _PROCESS is not None and _PROCESS.poll() is None:
|
||||
deadline = time.monotonic() + min(_PROCESS_HEALTH_GRACE, settings["timeout"])
|
||||
while time.monotonic() < deadline and _PROCESS.poll() is None:
|
||||
if _health(settings):
|
||||
return True, ""
|
||||
time.sleep(0.25)
|
||||
_stop_owned_process(_PROCESS)
|
||||
|
||||
try:
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import asyncio
|
||||
import os
|
||||
import signal
|
||||
import socket
|
||||
import subprocess
|
||||
import time
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
@ -301,6 +303,30 @@ def test_opencode_restarts_an_unhealthy_owned_process(live_opencode):
|
||||
assert views._health(settings)
|
||||
|
||||
|
||||
def test_opencode_preserves_a_transiently_unhealthy_owned_process(live_opencode):
|
||||
from archivebox.opencode import views
|
||||
|
||||
process = views._PROCESS
|
||||
assert process is not None
|
||||
views._signal_owned_process(process, signal.SIGSTOP)
|
||||
|
||||
def resume_process():
|
||||
time.sleep(2.5)
|
||||
views._signal_owned_process(process, signal.SIGCONT)
|
||||
|
||||
try:
|
||||
with ThreadPoolExecutor(max_workers=1) as executor:
|
||||
resumed = executor.submit(resume_process)
|
||||
ok, error = views._ensure_opencode(live_opencode.settings)
|
||||
resumed.result()
|
||||
finally:
|
||||
views._signal_owned_process(process, signal.SIGCONT)
|
||||
|
||||
assert ok, error
|
||||
assert views._PROCESS is process
|
||||
assert process.poll() is None
|
||||
|
||||
|
||||
def test_opencode_proxy_sse_response_is_unbuffered(admin_client, live_opencode):
|
||||
response = admin_client.get(
|
||||
"/admin/agent/opencode/global/event",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user