sync: 194 file da Baida98/AI@d7f0f6a2 (2026-08-30 07:28 UTC)

#150
by Baida07 - opened
api/public_status.py CHANGED
@@ -12,7 +12,7 @@ from typing import Any
12
 
13
  from fastapi import APIRouter
14
 
15
- from .public_snapshot import get_snapshot_client
16
 
17
  _logger = logging.getLogger("agente_ai.api.public_status")
18
  router = APIRouter(prefix="/api/public", tags=["public"])
@@ -26,7 +26,7 @@ _PUBLIC_FIELDS = (
26
  @router.get("/status")
27
  async def public_status() -> dict[str, Any]:
28
  """Restituisce esclusivamente lo snapshot deliberatamente pubblico."""
29
- client = get_snapshot_client()
30
  if client is None:
31
  return _degraded_snapshot("database_unavailable")
32
 
 
12
 
13
  from fastapi import APIRouter
14
 
15
+ from .state import sb
16
 
17
  _logger = logging.getLogger("agente_ai.api.public_status")
18
  router = APIRouter(prefix="/api/public", tags=["public"])
 
26
  @router.get("/status")
27
  async def public_status() -> dict[str, Any]:
28
  """Restituisce esclusivamente lo snapshot deliberatamente pubblico."""
29
+ client = sb()
30
  if client is None:
31
  return _degraded_snapshot("database_unavailable")
32
 
benchmark-extended.mjs ADDED
The diff for this file is too large to render. See raw diff
 
main.py CHANGED
@@ -253,9 +253,7 @@ async def startup_event():
253
  _logger.info("✅ BOOT: apply_rls_fix_sync() eseguito con successo.")
254
  except Exception as e:
255
  _logger.warning(f"⚠️ BOOT: apply_rls_fix_sync() fallito (non bloccante): {e}")
256
- # Schema e RLS sono gestiti dalle migrazioni versionate Supabase.
257
- # Non avviare auto-migrazioni in background: il boot deve restare
258
- # deterministico e non può dichiarare successo prima della migrazione.
259
  try:
260
  from api.public_snapshot import write_public_dashboard_snapshot
261
  snapshot_ok = await asyncio.wait_for(write_public_dashboard_snapshot(), timeout=12.0)
 
253
  _logger.info("✅ BOOT: apply_rls_fix_sync() eseguito con successo.")
254
  except Exception as e:
255
  _logger.warning(f"⚠️ BOOT: apply_rls_fix_sync() fallito (non bloccante): {e}")
256
+ asyncio.create_task(_run_auto_migration())
 
 
257
  try:
258
  from api.public_snapshot import write_public_dashboard_snapshot
259
  snapshot_ok = await asyncio.wait_for(write_public_dashboard_snapshot(), timeout=12.0)
scripts/lib/report-engine.mjs ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { mkdirSync, renameSync, writeFileSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+
4
+ const DEFAULT_REPORT_DIRECTORY = "/tmp/agente-ai";
5
+
6
+ function safeSegment(value) {
7
+ return String(value ?? "benchmark")
8
+ .trim()
9
+ .replace(/[^a-zA-Z0-9._-]+/g, "-")
10
+ .replace(/^-+|-+$/g, "")
11
+ .slice(0, 96) || "benchmark";
12
+ }
13
+
14
+ /**
15
+ * Persiste un artefatto diagnostico del runner senza incidere sui calcoli.
16
+ * Il write-then-rename evita file JSON parziali in caso di interruzione.
17
+ */
18
+ export function saveBenchmarkReport(reportName, payload) {
19
+ const reportDirectory = resolve(process.env.BENCHMARK_REPORT_DIR || DEFAULT_REPORT_DIRECTORY);
20
+ mkdirSync(reportDirectory, { recursive: true });
21
+
22
+ const safeName = safeSegment(reportName);
23
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
24
+ const finalPath = join(reportDirectory, `${safeName}-${stamp}.json`);
25
+ const temporaryPath = `${finalPath}.${process.pid}.tmp`;
26
+ const document = {
27
+ schemaVersion: "benchmark-report-v1",
28
+ generatedAt: new Date().toISOString(),
29
+ reportName: safeName,
30
+ ...payload,
31
+ };
32
+
33
+ writeFileSync(temporaryPath, `${JSON.stringify(document, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
34
+ renameSync(temporaryPath, finalPath);
35
+ return finalPath;
36
+ }
tests/test_public_snapshot_writer.py CHANGED
@@ -4,14 +4,10 @@ from api import public_snapshot
4
 
5
 
6
  class _FakeTable:
7
- def __init__(self, calls, failures=0):
8
  self.calls = calls
9
- self.failures = failures
10
 
11
  def upsert(self, row, on_conflict=None):
12
- if self.failures:
13
- self.failures -= 1
14
- raise RuntimeError("temporary Supabase failure")
15
  self.calls.append((row, on_conflict))
16
  return self
17
 
@@ -20,22 +16,17 @@ class _FakeTable:
20
 
21
 
22
  class _FakeClient:
23
- def __init__(self, failures=0):
24
  self.calls = []
25
- self.failures = failures
26
 
27
  def table(self, name):
28
  assert name == "public_dashboard_snapshot"
29
- return _FakeTable(self.calls, self.failures)
30
-
31
-
32
- def _run(coro):
33
- return asyncio.run(coro)
34
 
35
 
36
  def test_snapshot_writer_is_idempotent_and_counts_runtime_state(monkeypatch):
37
  fake = _FakeClient()
38
- monkeypatch.setattr(public_snapshot, "get_snapshot_client", lambda: fake)
39
  monkeypatch.setattr(
40
  public_snapshot,
41
  "_agent_tasks",
@@ -47,8 +38,8 @@ def test_snapshot_writer_is_idempotent_and_counts_runtime_state(monkeypatch):
47
  )
48
  monkeypatch.setattr(public_snapshot, "_loop_registry", {"session-1": object()})
49
 
50
- assert _run(public_snapshot.write_public_dashboard_snapshot()) is True
51
- assert _run(public_snapshot.write_public_dashboard_snapshot()) is True
52
 
53
  assert len(fake.calls) == 2
54
  first, second = fake.calls
@@ -62,34 +53,6 @@ def test_snapshot_writer_is_idempotent_and_counts_runtime_state(monkeypatch):
62
  assert first[0]["service_status"] == "operational"
63
 
64
 
65
- def test_snapshot_writer_retries_transient_failure(monkeypatch):
66
- calls = []
67
-
68
- class _RetryTable:
69
- def upsert(self, row, on_conflict=None):
70
- calls.append((row, on_conflict))
71
- if len(calls) < 3:
72
- raise RuntimeError("temporary Supabase failure")
73
- return self
74
-
75
- def execute(self):
76
- return object()
77
-
78
- class _RetryClient:
79
- def table(self, name):
80
- assert name == "public_dashboard_snapshot"
81
- return _RetryTable()
82
-
83
- monkeypatch.setattr(public_snapshot, "get_snapshot_client", lambda: _RetryClient())
84
- async def _no_sleep(_seconds):
85
- return None
86
-
87
- monkeypatch.setattr(public_snapshot.asyncio, "sleep", _no_sleep)
88
-
89
- assert _run(public_snapshot.write_public_dashboard_snapshot()) is True
90
- assert len(calls) == 3
91
-
92
-
93
- def test_snapshot_writer_returns_false_when_supabase_is_unavailable(monkeypatch):
94
- monkeypatch.setattr(public_snapshot, "get_snapshot_client", lambda: None)
95
- assert _run(public_snapshot.write_public_dashboard_snapshot()) is False
 
4
 
5
 
6
  class _FakeTable:
7
+ def __init__(self, calls):
8
  self.calls = calls
 
9
 
10
  def upsert(self, row, on_conflict=None):
 
 
 
11
  self.calls.append((row, on_conflict))
12
  return self
13
 
 
16
 
17
 
18
  class _FakeClient:
19
+ def __init__(self):
20
  self.calls = []
 
21
 
22
  def table(self, name):
23
  assert name == "public_dashboard_snapshot"
24
+ return _FakeTable(self.calls)
 
 
 
 
25
 
26
 
27
  def test_snapshot_writer_is_idempotent_and_counts_runtime_state(monkeypatch):
28
  fake = _FakeClient()
29
+ monkeypatch.setattr(public_snapshot, "sb", lambda: fake)
30
  monkeypatch.setattr(
31
  public_snapshot,
32
  "_agent_tasks",
 
38
  )
39
  monkeypatch.setattr(public_snapshot, "_loop_registry", {"session-1": object()})
40
 
41
+ assert asyncio.run(public_snapshot.write_public_dashboard_snapshot()) is True
42
+ assert asyncio.run(public_snapshot.write_public_dashboard_snapshot()) is True
43
 
44
  assert len(fake.calls) == 2
45
  first, second = fake.calls
 
53
  assert first[0]["service_status"] == "operational"
54
 
55
 
56
+ def test_snapshot_writer_is_non_blocking_when_supabase_is_unavailable(monkeypatch):
57
+ monkeypatch.setattr(public_snapshot, "sb", lambda: None)
58
+ assert asyncio.run(public_snapshot.write_public_dashboard_snapshot()) is False