""" backend/api/extended_benchmark.py — Benchmark multi-scenario per l'intero sistema. """ import asyncio import time import random from .execution_fabric import ExecutionFabric, DispatchRequest, ProviderKind, ProviderSpec, AlwaysOn, ProviderHealth from .token_rotator import rotator class ExtendedBenchmark: def __init__(self): self.fabric = ExecutionFabric() self.results = {} async def setup(self): # Configurazione flotta completa for i, char in enumerate(['A', 'B', 'C', 'D']): self.fabric._specs[f"sb-{char.lower()}"] = ProviderSpec( provider_id=f"sb-{char.lower()}", name=f"Supabase {char}", kind=ProviderKind.LOCAL, capabilities=["memory", "auth"], always_on=AlwaysOn.YES ) self.fabric._states[f"sb-{char.lower()}"] = type('State', (), {"health": ProviderHealth.OK})() self.fabric._specs["oracle-core"] = ProviderSpec( provider_id="oracle-core", name="Oracle Core", kind=ProviderKind.ORACLE, capabilities=["compute", "sandbox"], always_on=AlwaysOn.YES, timeout=60.0 ) self.fabric._states["oracle-core"] = type('State', (), {"health": ProviderHealth.OK})() self.fabric._specs["railway-core"] = ProviderSpec( provider_id="railway-core", name="Railway Space E", kind=ProviderKind.RAILWAY, capabilities=["compute", "sandbox"], always_on=AlwaysOn.YES ) self.fabric._states["railway-core"] = type('State', (), {"health": ProviderHealth.OK})() self.fabric._initialized = True async def scenario_normal_load(self): """Scenario 1: Carico normale, tutto funzionante.""" async def mock_ok(spec, req): return {"status": "ok", "latency": random.uniform(50, 200)} self.fabric._call_provider = mock_ok t0 = time.time() tasks = [self.fabric.dispatch(DispatchRequest(capability="memory")) for _ in range(10)] results = await asyncio.gather(*tasks) duration = (time.time() - t0) * 1000 self.results["normal_load"] = {"avg_latency": duration/10, "success_rate": 100.0} async def scenario_cascading_failure(self): """Scenario 2: Fallimento a catena Supabase A -> B -> C -> D.""" failed_providers = set() async def mock_cascade(spec, req): if spec.provider_id in ["sb-a", "sb-b", "sb-c"]: failed_providers.add(spec.provider_id) return {"status_code": 429} return {"status": "ok", "provider": spec.name} self.fabric._call_provider = mock_cascade t0 = time.time() result = await self.fabric.dispatch(DispatchRequest(capability="memory")) duration = (time.time() - t0) * 1000 self.results["cascading_failure"] = { "duration": duration, "final_provider": result.provider_name, "rotations": len(failed_providers) } async def scenario_oracle_stress(self): """Scenario 3: Oracle saturo, fallback immediato su Railway.""" async def mock_oracle_down(spec, req): if spec.kind == ProviderKind.ORACLE: await asyncio.sleep(0.5) # Simula attesa timeout raise Exception("Oracle Overloaded") return {"status": "ok", "from": "railway"} self.fabric._call_provider = mock_oracle_down t0 = time.time() result = await self.fabric.dispatch(DispatchRequest(capability="compute", provider_hint="oracle-core")) duration = (time.time() - t0) * 1000 self.results["oracle_fallback"] = {"duration": duration, "provider": result.provider_name} async def run_all(self): print("🚀 Avvio Benchmark Multi-Scenario...") await self.setup() await self.scenario_normal_load() await self.scenario_cascading_failure() await self.scenario_oracle_stress() print("\n--- REPORT FINALE ---") for name, data in self.results.items(): print(f"[{name.upper()}]") for k, v in data.items(): print(f" - {k}: {v}") print("----------------------") if __name__ == "__main__": asyncio.run(ExtendedBenchmark().run_all())