mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-08-17 20:50:34 +00:00
Add proof worker pool routing
This commit is contained in:
parent
e18a284082
commit
f73d49b342
5 changed files with 67 additions and 10 deletions
|
|
@ -116,7 +116,7 @@ fi
|
||||||
export HOME=/var/lib/language-proof-server
|
export HOME=/var/lib/language-proof-server
|
||||||
export PATH="$HOME/.elan/bin:$PATH"
|
export PATH="$HOME/.elan/bin:$PATH"
|
||||||
cd /srv/research-stack/0-Core-Formalism/lean/Semantics
|
cd /srv/research-stack/0-Core-Formalism/lean/Semantics
|
||||||
runuser -u proofsrv -- sh -lc "cd /srv/research-stack/0-Core-Formalism/lean/Semantics && export PATH=/var/lib/language-proof-server/.elan/bin:\$PATH && elan toolchain install \"\$(cat lean-toolchain)\" && lake update"
|
runuser -u proofsrv -- sh -lc "cd /srv/research-stack/0-Core-Formalism/lean/Semantics && export PATH=/var/lib/language-proof-server/.elan/bin:\$PATH && elan toolchain install \"\$(cat lean-toolchain)\" || true; lake update"
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable --now language-proof-server.service
|
systemctl enable --now language-proof-server.service
|
||||||
systemctl --no-pager --full status language-proof-server.service | sed -n "1,18p"
|
systemctl --no-pager --full status language-proof-server.service | sed -n "1,18p"
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,11 @@ def command_env() -> dict[str, str]:
|
||||||
return env
|
return env
|
||||||
|
|
||||||
|
|
||||||
|
def command_prefix() -> list[str]:
|
||||||
|
raw = os.environ.get("PROOF_COMMAND_PREFIX", "").strip()
|
||||||
|
return shlex.split(raw) if raw else []
|
||||||
|
|
||||||
|
|
||||||
def run_command(
|
def run_command(
|
||||||
command: list[str],
|
command: list[str],
|
||||||
cwd: Path,
|
cwd: Path,
|
||||||
|
|
@ -112,10 +117,11 @@ def run_command(
|
||||||
timeout_s: int,
|
timeout_s: int,
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
started = time.time()
|
started = time.time()
|
||||||
command_display = " ".join(shlex.quote(part) for part in command)
|
full_command = command_prefix() + command
|
||||||
|
command_display = " ".join(shlex.quote(part) for part in full_command)
|
||||||
try:
|
try:
|
||||||
proc = subprocess.run(
|
proc = subprocess.run(
|
||||||
command,
|
full_command,
|
||||||
cwd=str(cwd),
|
cwd=str(cwd),
|
||||||
env=command_env(),
|
env=command_env(),
|
||||||
text=True,
|
text=True,
|
||||||
|
|
@ -178,6 +184,7 @@ def health() -> dict[str, Any]:
|
||||||
checks: dict[str, Any] = {
|
checks: dict[str, Any] = {
|
||||||
"repo_dir": str(repo_dir()),
|
"repo_dir": str(repo_dir()),
|
||||||
"lean_root": str(root),
|
"lean_root": str(root),
|
||||||
|
"proof_command_prefix": command_prefix(),
|
||||||
"lean_root_exists": root.exists(),
|
"lean_root_exists": root.exists(),
|
||||||
"lakefile_exists": (root / "lakefile.toml").exists(),
|
"lakefile_exists": (root / "lakefile.toml").exists(),
|
||||||
"lean_toolchain_exists": (root / "lean-toolchain").exists(),
|
"lean_toolchain_exists": (root / "lean-toolchain").exists(),
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -38,7 +39,29 @@ def base_url() -> str:
|
||||||
return os.environ.get("PROOF_SERVER_URL", DEFAULT_URL).rstrip("/")
|
return os.environ.get("PROOF_SERVER_URL", DEFAULT_URL).rstrip("/")
|
||||||
|
|
||||||
|
|
||||||
def request_json(path: str, payload: dict[str, Any] | None = None, timeout: int = 120) -> dict[str, Any]:
|
def proof_urls() -> list[str]:
|
||||||
|
raw = os.environ.get("PROOF_SERVER_URLS", "").strip()
|
||||||
|
urls = [item.strip().rstrip("/") for item in raw.split(",") if item.strip()]
|
||||||
|
if not urls:
|
||||||
|
urls = [base_url()]
|
||||||
|
return list(dict.fromkeys(urls))
|
||||||
|
|
||||||
|
|
||||||
|
def ordered_urls(payload: dict[str, Any] | None = None) -> list[str]:
|
||||||
|
urls = proof_urls()
|
||||||
|
if len(urls) <= 1 or payload is None:
|
||||||
|
return urls
|
||||||
|
key = str(payload.get("name") or payload.get("target") or payload.get("agent") or "")
|
||||||
|
offset = int(hashlib.sha256(key.encode("utf-8")).hexdigest(), 16) % len(urls)
|
||||||
|
return urls[offset:] + urls[:offset]
|
||||||
|
|
||||||
|
|
||||||
|
def request_json_from(
|
||||||
|
url: str,
|
||||||
|
path: str,
|
||||||
|
payload: dict[str, Any] | None = None,
|
||||||
|
timeout: int = 120,
|
||||||
|
) -> dict[str, Any]:
|
||||||
headers = {"Accept": "application/json", "User-Agent": f"{SERVER_NAME}/{SERVER_VERSION}"}
|
headers = {"Accept": "application/json", "User-Agent": f"{SERVER_NAME}/{SERVER_VERSION}"}
|
||||||
body = None
|
body = None
|
||||||
method = "GET"
|
method = "GET"
|
||||||
|
|
@ -49,10 +72,13 @@ def request_json(path: str, payload: dict[str, Any] | None = None, timeout: int
|
||||||
auth = token()
|
auth = token()
|
||||||
if auth:
|
if auth:
|
||||||
headers["Authorization"] = f"Bearer {auth}"
|
headers["Authorization"] = f"Bearer {auth}"
|
||||||
req = urllib.request.Request(f"{base_url()}{path}", data=body, headers=headers, method=method)
|
req = urllib.request.Request(f"{url}{path}", data=body, headers=headers, method=method)
|
||||||
try:
|
try:
|
||||||
with urllib.request.urlopen(req, timeout=timeout) as response:
|
with urllib.request.urlopen(req, timeout=timeout) as response:
|
||||||
return json.loads(response.read().decode("utf-8"))
|
data = json.loads(response.read().decode("utf-8"))
|
||||||
|
if isinstance(data, dict):
|
||||||
|
data.setdefault("proof_server_url", url)
|
||||||
|
return data
|
||||||
except urllib.error.HTTPError as exc:
|
except urllib.error.HTTPError as exc:
|
||||||
text = exc.read().decode("utf-8", errors="replace")
|
text = exc.read().decode("utf-8", errors="replace")
|
||||||
try:
|
try:
|
||||||
|
|
@ -61,20 +87,34 @@ def request_json(path: str, payload: dict[str, Any] | None = None, timeout: int
|
||||||
data = {"error": text}
|
data = {"error": text}
|
||||||
data["http_status"] = exc.code
|
data["http_status"] = exc.code
|
||||||
data["ok"] = False
|
data["ok"] = False
|
||||||
|
data["proof_server_url"] = url
|
||||||
return data
|
return data
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
return {"ok": False, "error": f"{type(exc).__name__}: {exc}"}
|
return {"ok": False, "error": f"{type(exc).__name__}: {exc}", "proof_server_url": url}
|
||||||
|
|
||||||
|
|
||||||
|
def request_json(path: str, payload: dict[str, Any] | None = None, timeout: int = 120) -> dict[str, Any]:
|
||||||
|
failures = []
|
||||||
|
for url in ordered_urls(payload):
|
||||||
|
data = request_json_from(url, path, payload, timeout)
|
||||||
|
if data.get("ok"):
|
||||||
|
return data
|
||||||
|
failures.append(data)
|
||||||
|
return {"ok": False, "error": "all proof servers failed", "failures": failures}
|
||||||
|
|
||||||
|
|
||||||
def tool_status(_: dict[str, Any]) -> dict[str, Any]:
|
def tool_status(_: dict[str, Any]) -> dict[str, Any]:
|
||||||
health = request_json("/health", timeout=10)
|
nodes = [request_json_from(url, "/health", timeout=10) for url in proof_urls()]
|
||||||
|
healthy = [node for node in nodes if node.get("ok")]
|
||||||
return {
|
return {
|
||||||
"ok": bool(health.get("ok")),
|
"ok": bool(healthy),
|
||||||
"server": SERVER_NAME,
|
"server": SERVER_NAME,
|
||||||
"version": SERVER_VERSION,
|
"version": SERVER_VERSION,
|
||||||
"proof_server_url": base_url(),
|
"proof_server_url": base_url(),
|
||||||
|
"proof_server_urls": proof_urls(),
|
||||||
"token_configured": bool(token()),
|
"token_configured": bool(token()),
|
||||||
"health": health,
|
"health": healthy[0] if healthy else (nodes[0] if nodes else {"ok": False}),
|
||||||
|
"nodes": nodes,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,15 @@ slow or unavailable. The MCP server fronts the dedicated proof service at
|
||||||
`~/.config/ene/language-proof-server.token`, and returns receipt-bearing
|
`~/.config/ene/language-proof-server.token`, and returns receipt-bearing
|
||||||
responses.
|
responses.
|
||||||
|
|
||||||
|
Active proof-worker pool:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://54.236.176.28:8787 AWS EC2 dedicated proof server
|
||||||
|
http://100.110.163.82:8787 361395-1 Netcup proof worker
|
||||||
|
http://100.102.173.61:8787 nixos-laptop proof worker
|
||||||
|
http://100.85.244.73:8787 nixos-steamdeck-1 proof worker
|
||||||
|
```
|
||||||
|
|
||||||
Primary tools:
|
Primary tools:
|
||||||
|
|
||||||
- `proof_status` for health and token wiring.
|
- `proof_status` for health and token wiring.
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
],
|
],
|
||||||
"environment": {
|
"environment": {
|
||||||
"PROOF_SERVER_URL": "http://54.236.176.28:8787",
|
"PROOF_SERVER_URL": "http://54.236.176.28:8787",
|
||||||
|
"PROOF_SERVER_URLS": "http://54.236.176.28:8787,http://100.110.163.82:8787,http://100.102.173.61:8787,http://100.85.244.73:8787",
|
||||||
"PROOF_SERVER_TOKEN_FILE": "/home/allaun/.config/ene/language-proof-server.token"
|
"PROOF_SERVER_TOKEN_FILE": "/home/allaun/.config/ene/language-proof-server.token"
|
||||||
},
|
},
|
||||||
"enabled": true
|
"enabled": true
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue