Skip to content

Commit 5b455ff

Browse files
committed
labs: scope and parallelize official client drift checks
1 parent 54380a8 commit 5b455ff

1 file changed

Lines changed: 50 additions & 10 deletions

File tree

scripts/check_nuvio_client_upstreams.py

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import subprocess
88
import sys
99
import tempfile
10+
from concurrent.futures import ThreadPoolExecutor
1011
from datetime import datetime, timezone
1112
from pathlib import Path
1213
from typing import Any
@@ -205,7 +206,17 @@ def current_head(repository: str, branch: str) -> str:
205206
return sha
206207

207208

208-
def compare(repository: str, base: str, head: str) -> dict[str, Any]:
209+
def compare(
210+
repository: str,
211+
base: str,
212+
head: str,
213+
patch_rules: list[str] | None = None,
214+
) -> dict[str, Any]:
215+
"""Compare refs while materializing patches only for semantic-review paths.
216+
217+
Hard contract changes need only their filenames. Diffing every changed file was
218+
the dominant cost of the native Lab resolver and provided no extra evidence.
219+
"""
209220
with tempfile.TemporaryDirectory(prefix="niakvio-client-drift-") as tmp:
210221
work = Path(tmp)
211222
run_git(["init", "--quiet"], cwd=work)
@@ -244,8 +255,12 @@ def compare(repository: str, base: str, head: str) -> dict[str, Any]:
244255
timeout=30,
245256
)
246257
files = [name.strip() for name in names.splitlines() if name.strip()]
258+
if patch_rules:
259+
patch_files = [name for name in files if path_matches(name, patch_rules)][:250]
260+
else:
261+
patch_files = files[:250]
247262
patches: dict[str, str] = {}
248-
for filename in files[:250]:
263+
for filename in patch_files:
249264
patch = run_git(
250265
[
251266
"diff",
@@ -315,7 +330,7 @@ def inspect_client(key: str, row: dict[str, Any], sources: dict[str, Any] | None
315330
if head == accepted_ref:
316331
return result
317332

318-
comparison = compare(repository, accepted_ref, head)
333+
comparison = compare(repository, accepted_ref, head, semantic_rules)
319334
status = str(comparison.get("status") or "unknown")
320335
patches = comparison.get("patches") or {}
321336
files = [
@@ -389,6 +404,8 @@ def apply_safe_state(
389404
advanced: list[str] = []
390405

391406
for key, row in (config.get("clients") or {}).items():
407+
if key not in results:
408+
continue
392409
result = results[key]
393410
contract_ref = str(row.get("verified_ref") or "")
394411
state = clients.get(key)
@@ -431,6 +448,11 @@ def main() -> int:
431448
"--output",
432449
default=str(ROOT / "health-output" / "nuvio-client-upstream-status.json"),
433450
)
451+
parser.add_argument(
452+
"--clients",
453+
nargs="+",
454+
help="Inspect only these configured client ids. Omit for the full registry.",
455+
)
434456
parser.add_argument(
435457
"--no-fail",
436458
action="store_true",
@@ -460,12 +482,20 @@ def main() -> int:
460482
"Nuvio client upstream configuration invalid:\n- " + "\n- ".join(config_errors)
461483
)
462484

485+
all_clients = config.get("clients") or {}
486+
requested = args.clients or list(all_clients)
487+
unknown = [key for key in requested if key not in all_clients]
488+
if unknown:
489+
raise SystemExit("unknown Nuvio client ids: " + ", ".join(unknown))
490+
selected_items = [(key, all_clients[key]) for key in requested]
491+
463492
now = datetime.now(timezone.utc).isoformat()
464493
report: dict[str, Any] = {
465-
"schema_version": 3,
494+
"schema_version": 4,
466495
"generated_at": now,
467-
"transport": "git-ls-remote-plus-partial-tree-diff",
496+
"transport": "parallel-git-ls-remote-plus-targeted-partial-tree-diff",
468497
"policy": config.get("policy") or {},
498+
"selected_clients": requested,
469499
"clients": {},
470500
"review_required": [],
471501
"safe_advance_available": [],
@@ -474,12 +504,11 @@ def main() -> int:
474504
"inconclusive": [],
475505
}
476506

477-
failures: list[str] = []
478-
for key, row in (config.get("clients") or {}).items():
507+
def inspect_one(key: str, row: dict[str, Any]) -> dict[str, Any]:
479508
try:
480-
result = resilient_inspect_client(str(key), row, sources)
509+
return resilient_inspect_client(str(key), row, sources)
481510
except Exception as error:
482-
result = {
511+
return {
483512
"id": key,
484513
"repository": row.get("repository"),
485514
"branch": row.get("branch"),
@@ -488,6 +517,15 @@ def main() -> int:
488517
"review_required": True,
489518
"error": f"{type(error).__name__}: {error}",
490519
}
520+
521+
worker_count = max(1, min(3, len(selected_items)))
522+
with ThreadPoolExecutor(max_workers=worker_count, thread_name_prefix="nuvio-drift") as pool:
523+
futures = {key: pool.submit(inspect_one, key, row) for key, row in selected_items}
524+
inspected = {key: futures[key].result() for key, _row in selected_items}
525+
526+
failures: list[str] = []
527+
for key, _row in selected_items:
528+
result = inspected[key]
491529
report["clients"][key] = result
492530
status = result.get("status")
493531
if status == "verified":
@@ -529,7 +567,8 @@ def main() -> int:
529567

530568
if args.apply_safe_advance and not failures and not report["inconclusive"]:
531569
advanced = apply_safe_state(sources, config, report["clients"], now)
532-
if advanced or "nuvio_client_compatibility" not in load(sources_path):
570+
previous_sources = load(sources_path) if sources_path.is_file() else {}
571+
if advanced or "nuvio_client_compatibility" not in previous_sources:
533572
dump(sources_path, sources)
534573
report["auto_advanced"] = advanced
535574
for key in advanced:
@@ -555,6 +594,7 @@ def main() -> int:
555594

556595
print(
557596
"Nuvio client upstream drift check: "
597+
f"selected={','.join(requested) or '-'}; "
558598
f"verified={','.join(report['verified']) or '-'}; "
559599
f"safe={','.join(report['safe_advance_available']) or '-'}; "
560600
f"auto_advanced={','.join(report['auto_advanced']) or '-'}; "

0 commit comments

Comments
 (0)