Skip to main content
Glama
test_cache_circuit_breaker.py‱13.1 kB
#!/usr/bin/env python3 """ đŸ§Ș Test du systĂšme de cache et circuit breaker Script de test pour valider les fonctionnalitĂ©s de la Phase 2.4 """ import asyncio import requests import json import time from datetime import datetime import sys BASE_URL = "http://localhost:3003" def print_header(title: str): """Affiche un en-tĂȘte de section""" print(f"\n{'='*60}") print(f"đŸ§Ș {title}") print(f"{'='*60}") def print_step(step: str): """Affiche une Ă©tape de test""" print(f"\nâžĄïž {step}") def print_result(success: bool, message: str): """Affiche le rĂ©sultat d'un test""" icon = "✅" if success else "❌" print(f"{icon} {message}") async def test_health_check(): """Test de santĂ© du serveur""" print_step("Test de santĂ© du serveur") try: response = requests.get(f"{BASE_URL}/health", timeout=5) if response.status_code == 200: data = response.json() print_result(True, f"Serveur en ligne - Status: {data.get('status', 'unknown')}") return True else: print_result(False, f"Serveur rĂ©pond avec code {response.status_code}") return False except Exception as e: print_result(False, f"Serveur inaccessible: {e}") return False async def test_cache_performance(): """Test des performances du cache""" print_header("TEST PERFORMANCE CACHE") # CrĂ©er une session MCP print_step("CrĂ©ation d'une session MCP") try: response = requests.post(f"{BASE_URL}/mcp/initialize", json={ 'protocolVersion': '2024-11-05', 'capabilities': {}, 'clientInfo': {'name': 'cache_test', 'version': '1.0'} }, timeout=10) if response.status_code != 200: print_result(False, f"Échec crĂ©ation session: {response.status_code}") return False session_data = response.json() session_id = session_data['result']['session_id'] print_result(True, f"Session créée: {session_id}") except Exception as e: print_result(False, f"Erreur crĂ©ation session: {e}") return False # Test 1: Premier appel (MISS cache) print_step("Test 1: Premier appel list_tools (CACHE MISS attendu)") start_time = time.time() try: response = requests.post(f"{BASE_URL}/mcp/tools/list", headers={'X-Session-ID': session_id}, json={'jsonrpc': '2.0', 'id': 1, 'method': 'tools/list', 'params': {}}, timeout=10) first_call_time = time.time() - start_time if response.status_code == 200: tools = response.json()['result']['tools'] print_result(True, f"Outils rĂ©cupĂ©rĂ©s en {first_call_time:.3f}s ({len(tools)} outils)") else: print_result(False, f"Échec rĂ©cupĂ©ration outils: {response.status_code}") return False except Exception as e: print_result(False, f"Erreur appel tools/list: {e}") return False # Test 2: DeuxiĂšme appel immĂ©diat (HIT cache) print_step("Test 2: DeuxiĂšme appel list_tools (CACHE HIT attendu)") start_time = time.time() try: response = requests.post(f"{BASE_URL}/mcp/tools/list", headers={'X-Session-ID': session_id}, json={'jsonrpc': '2.0', 'id': 2, 'method': 'tools/list', 'params': {}}, timeout=10) second_call_time = time.time() - start_time if response.status_code == 200: tools = response.json()['result']['tools'] speedup = first_call_time / second_call_time if second_call_time > 0 else float('inf') print_result(True, f"Outils rĂ©cupĂ©rĂ©s en {second_call_time:.3f}s - AccĂ©lĂ©ration: {speedup:.1f}x") if second_call_time < first_call_time * 0.5: print_result(True, "Cache fonctionne correctement (>50% plus rapide)") else: print_result(False, "Cache ne semble pas fonctionner (pas d'accĂ©lĂ©ration significative)") else: print_result(False, f"Échec deuxiĂšme appel: {response.status_code}") return False except Exception as e: print_result(False, f"Erreur deuxiĂšme appel: {e}") return False # Test 3: Appels multiples pour tester cache rĂ©ponses print_step("Test 3: Appels multiples get_entities (test cache rĂ©ponses)") total_time = 0 call_count = 5 for i in range(call_count): start_time = time.time() try: response = requests.post(f"{BASE_URL}/mcp/tools/call", headers={'X-Session-ID': session_id}, json={ 'jsonrpc': '2.0', 'id': 10 + i, 'method': 'tools/call', 'params': { 'name': 'get_entities', 'arguments': {'domain': 'light'} } }, timeout=10) call_time = time.time() - start_time total_time += call_time if response.status_code == 200: print(f" Appel {i+1}: {call_time:.3f}s") else: print_result(False, f"Échec appel {i+1}: {response.status_code}") except Exception as e: print_result(False, f"Erreur appel {i+1}: {e}") avg_time = total_time / call_count print_result(True, f"Temps moyen sur {call_count} appels: {avg_time:.3f}s") return True async def test_circuit_breaker(): """Test du circuit breaker""" print_header("TEST CIRCUIT BREAKER") print_step("RĂ©cupĂ©ration mĂ©triques initiales") try: response = requests.get(f"{BASE_URL}/admin/metrics", timeout=10) if response.status_code == 200: initial_metrics = response.json()['metrics'] cb_stats = initial_metrics['circuit_breaker'] print_result(True, f"Circuit breaker Ă©tat: {cb_stats['state']}") print(f" Total requĂȘtes: {cb_stats['total_requests']}") print(f" RequĂȘtes rĂ©ussies: {cb_stats['successful_requests']}") print(f" Taux de succĂšs: {cb_stats['success_rate_percent']}%") else: print_result(False, f"Échec rĂ©cupĂ©ration mĂ©triques: {response.status_code}") return False except Exception as e: print_result(False, f"Erreur rĂ©cupĂ©ration mĂ©triques: {e}") return False # Note: Dans un environnement de test rĂ©el, on pourrait forcer des erreurs # Pour l'instant, on vĂ©rifie juste que le circuit breaker fonctionne print_step("Circuit breaker en mode normal") print_result(True, "Circuit breaker opĂ©rationnel en mode CLOSED") return True async def test_metrics_endpoint(): """Test de l'endpoint mĂ©triques""" print_header("TEST ENDPOINT MÉTRIQUES") print_step("RĂ©cupĂ©ration mĂ©triques complĂštes") try: response = requests.get(f"{BASE_URL}/admin/metrics", timeout=10) if response.status_code == 200: data = response.json() metrics = data['metrics'] print_result(True, "MĂ©triques rĂ©cupĂ©rĂ©es avec succĂšs") # Afficher les mĂ©triques importantes print(f"\\n📊 MÉTRIQUES SYSTÈME:") print(f" Uptime: {metrics['uptime_seconds']:.1f}s") print(f"\\n🧠 CACHE OUTILS:") tools_cache = metrics['tools_cache'] print(f" Taille: {tools_cache['size']}/{tools_cache['max_size']}") print(f" Hits: {tools_cache['hits']}, Misses: {tools_cache['misses']}") print(f" Taux de hit: {tools_cache['hit_rate_percent']}%") print(f" TTL par dĂ©faut: {tools_cache['default_ttl']}s") print(f"\\nđŸ’Ÿ CACHE RÉPONSES:") resp_cache = metrics['response_cache'] print(f" Taille: {resp_cache['size']}/{resp_cache['max_size']}") print(f" Hits: {resp_cache['hits']}, Misses: {resp_cache['misses']}") print(f" Taux de hit: {resp_cache['hit_rate_percent']}%") print(f"\\n🔌 CIRCUIT BREAKER:") cb = metrics['circuit_breaker'] print(f" État: {cb['state']}") print(f" Disponible: {cb['is_available']}") print(f" RequĂȘtes totales: {cb['total_requests']}") print(f" Taux de succĂšs: {cb['success_rate_percent']}%") print(f"\\n📋 GESTION SESSIONS:") if 'session_management' in metrics: sm = metrics['session_management'] print(f" Sessions actives: {sm['active_sessions']}") print(f" RequĂȘtes traitĂ©es: {sm['total_requests_processed']}") print(f" Taille queue: {sm['queue_size']}") if 'queue_stats' in sm: qs = sm['queue_stats'] print(f" Performance queue:") print(f" - Taux de succĂšs: {qs['performance']['success_rate_percent']}%") print(f" - Temps moyen: {qs['performance']['avg_processing_time_ms']}ms") print(f" - Charge actuelle: {qs['capacity']['current_load_percent']}%") return True else: print_result(False, f"Échec rĂ©cupĂ©ration mĂ©triques: {response.status_code}") return False except Exception as e: print_result(False, f"Erreur rĂ©cupĂ©ration mĂ©triques: {e}") return False async def test_cache_management(): """Test de la gestion du cache""" print_header("TEST GESTION CACHE") print_step("Test vidage du cache") try: response = requests.post(f"{BASE_URL}/admin/cache/clear", timeout=10) if response.status_code == 200: result = response.json() print_result(True, f"Cache vidĂ©: {result['message']}") else: print_result(False, f"Échec vidage cache: {response.status_code}") return False except Exception as e: print_result(False, f"Erreur vidage cache: {e}") return False # VĂ©rifier que le cache est vide print_step("VĂ©rification cache vide") try: response = requests.get(f"{BASE_URL}/admin/metrics", timeout=10) if response.status_code == 200: metrics = response.json()['metrics'] tools_size = metrics['tools_cache']['size'] resp_size = metrics['response_cache']['size'] if tools_size == 0 and resp_size == 0: print_result(True, "Cache correctement vidĂ©") else: print_result(False, f"Cache non vide - tools: {tools_size}, responses: {resp_size}") else: print_result(False, f"Échec vĂ©rification cache: {response.status_code}") return False except Exception as e: print_result(False, f"Erreur vĂ©rification cache: {e}") return False return True async def main(): """Fonction principale de test""" print_header("TEST PHASE 2.4 - CACHE L1 & CIRCUIT BREAKER") print(f"🕒 DĂ©marrage des tests: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") # Test prĂ©liminaire if not await test_health_check(): print_result(False, "❌ SERVEUR INACCESSIBLE - ARRÊT DES TESTS") return False # Tests principaux tests = [ ("Performance Cache", test_cache_performance), ("Circuit Breaker", test_circuit_breaker), ("Endpoint MĂ©triques", test_metrics_endpoint), ("Gestion Cache", test_cache_management), ] results = [] for test_name, test_func in tests: try: result = await test_func() results.append((test_name, result)) except Exception as e: print_result(False, f"ERREUR CRITIQUE dans {test_name}: {e}") results.append((test_name, False)) # RĂ©sumĂ© final print_header("RÉSUMÉ DES TESTS") total_tests = len(results) passed_tests = sum(1 for _, result in results if result) for test_name, result in results: status = "✅ PASSÉ" if result else "❌ ÉCHEC" print(f"{status} - {test_name}") print(f"\\n📊 RÉSULTAT FINAL: {passed_tests}/{total_tests} tests rĂ©ussis") if passed_tests == total_tests: print_result(True, "🎉 TOUS LES TESTS DE LA PHASE 2.4 SONT PASSÉS!") print("🚀 Phase 2.4 (Cache L1 & Circuit Breaker) - TERMINÉE AVEC SUCCÈS") return True else: print_result(False, f"❌ {total_tests - passed_tests} tests ont Ă©chouĂ©") return False if __name__ == "__main__": # ExĂ©cuter les tests success = asyncio.run(main()) sys.exit(0 if success else 1)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Jonathan97480/McpHomeAssistant'

If you have feedback or need assistance with the MCP directory API, please join our Discord server