1
0
Fork 0
Code Issues Pull requests Projects Releases 2 Packages Wiki Activity Actions Pages

Manage graph viewers with a supervised local service

This commit is contained in:
Andraxion 2026-07-25 00:17:21 -04:00
parent eb48ba1a51
commit 7c87536167
14 changed files with 1027 additions and 103 deletions

View file

@ -5,6 +5,7 @@ from __future__ import annotations
import argparse
import json
import socket
import sys
import time
from contextlib import suppress
from typing import cast
@ -15,11 +16,21 @@ from .visualization import VisualizationRunner
def _parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(prog="docforge-visualization-worker")
parser.add_argument("--control-fd", type=int, required=True)
control = parser.add_mutually_exclusive_group(required=True)
control.add_argument("--control-fd", type=int)
control.add_argument("--request-stdin", action="store_true")
return parser
def _read_request(control: socket.socket) -> dict[str, object]:
def _read_request(control: socket.socket | None) -> dict[str, object]:
if control is None:
payload = sys.stdin.buffer.readline(1_000_001)
if not payload or len(payload) > 1_000_000:
raise ValueError("Visualization launch request is invalid")
request: object = json.loads(payload)
if not isinstance(request, dict):
raise ValueError("Visualization launch request is invalid")
return cast(dict[str, object], request)
chunks: list[bytes] = []
size = 0
while True:
@ -39,9 +50,18 @@ def _read_request(control: socket.socket) -> dict[str, object]:
return cast(dict[str, object], request)
def _send_response(control: socket.socket | None, payload: dict[str, object]) -> None:
encoded = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8") + b"\n"
if control is None:
sys.stdout.buffer.write(encoded)
sys.stdout.buffer.flush()
else:
control.sendall(encoded)
def main(argv: list[str] | None = None) -> int:
arguments = _parser().parse_args(argv)
control = socket.socket(fileno=arguments.control_fd)
control = None if arguments.request_stdin else socket.socket(fileno=arguments.control_fd)
runner: VisualizationRunner | None = None
try:
request = _read_request(control)
@ -73,29 +93,16 @@ def main(argv: list[str] | None = None) -> int:
query=query,
depth=depth,
)
control.sendall(
json.dumps(
{"status": "ok", "visualization": visualization},
sort_keys=True,
separators=(",", ":"),
).encode("utf-8")
+ b"\n"
)
_send_response(control, {"status": "ok", "visualization": visualization})
except (DocForgeError, KeyError, OSError, TypeError, ValueError) as error:
with suppress(OSError):
control.sendall(
json.dumps(
{"status": "error", "error": type(error).__name__},
sort_keys=True,
separators=(",", ":"),
).encode("utf-8")
+ b"\n"
)
_send_response(control, {"status": "error", "error": type(error).__name__})
if runner is not None:
runner.stop()
return 2
finally:
control.close()
if control is not None:
control.close()
while runner.is_running():
time.sleep(0.25)