- Add Prometheus metrics for marketplace API throughput and error rates with new dashboard panels - Implement confidential transaction models with encryption support and access control - Add key management system with registration, rotation, and audit logging - Create services and registry routers for service discovery and management - Integrate ZK proof generation for privacy-preserving receipts - Add metrics instru
216 lines
7.6 KiB
Python
216 lines
7.6 KiB
Python
"""
|
|
Plugin discovery and matching system
|
|
"""
|
|
|
|
import asyncio
|
|
import logging
|
|
from typing import Dict, List, Set, Optional
|
|
import requests
|
|
|
|
from .registry import registry
|
|
from .base import ServicePlugin
|
|
from .exceptions import PluginNotFoundError
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ServiceDiscovery:
|
|
"""Discovers and matches services to plugins"""
|
|
|
|
def __init__(self, pool_hub_url: str, miner_id: str):
|
|
self.pool_hub_url = pool_hub_url
|
|
self.miner_id = miner_id
|
|
self.enabled_services: Set[str] = set()
|
|
self.service_configs: Dict[str, Dict] = {}
|
|
self._last_update = 0
|
|
self._update_interval = 60 # seconds
|
|
|
|
async def start(self) -> None:
|
|
"""Start the discovery service"""
|
|
logger.info("Starting service discovery")
|
|
|
|
# Initialize plugin registry
|
|
await registry.initialize()
|
|
|
|
# Initial sync
|
|
await self.sync_services()
|
|
|
|
# Start background sync task
|
|
asyncio.create_task(self._sync_loop())
|
|
|
|
async def sync_services(self) -> None:
|
|
"""Sync enabled services from pool-hub"""
|
|
try:
|
|
# Get service configurations from pool-hub
|
|
response = requests.get(
|
|
f"{self.pool_hub_url}/v1/services/",
|
|
headers={"X-Miner-ID": self.miner_id}
|
|
)
|
|
response.raise_for_status()
|
|
|
|
services = response.json()
|
|
|
|
# Update local state
|
|
new_enabled = set()
|
|
new_configs = {}
|
|
|
|
for service in services:
|
|
if service.get("enabled", False):
|
|
service_id = service["service_type"]
|
|
new_enabled.add(service_id)
|
|
new_configs[service_id] = service
|
|
|
|
# Find changes
|
|
added = new_enabled - self.enabled_services
|
|
removed = self.enabled_services - new_enabled
|
|
updated = set()
|
|
|
|
for service_id in self.enabled_services & new_enabled:
|
|
if new_configs[service_id] != self.service_configs.get(service_id):
|
|
updated.add(service_id)
|
|
|
|
# Apply changes
|
|
for service_id in removed:
|
|
await self._disable_service(service_id)
|
|
|
|
for service_id in added:
|
|
await self._enable_service(service_id, new_configs[service_id])
|
|
|
|
for service_id in updated:
|
|
await self._update_service(service_id, new_configs[service_id])
|
|
|
|
# Update state
|
|
self.enabled_services = new_enabled
|
|
self.service_configs = new_configs
|
|
self._last_update = asyncio.get_event_loop().time()
|
|
|
|
logger.info(f"Synced services: {len(self.enabled_services)} enabled")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to sync services: {e}")
|
|
|
|
async def _enable_service(self, service_id: str, config: Dict) -> None:
|
|
"""Enable a service"""
|
|
try:
|
|
# Check if plugin exists
|
|
if service_id not in registry.list_plugins():
|
|
logger.warning(f"No plugin available for service: {service_id}")
|
|
return
|
|
|
|
# Load plugin
|
|
plugin = registry.load_plugin(service_id)
|
|
|
|
# Validate hardware requirements
|
|
await self._validate_hardware_requirements(plugin, config)
|
|
|
|
# Configure plugin if needed
|
|
if hasattr(plugin, 'configure'):
|
|
await plugin.configure(config.get('config', {}))
|
|
|
|
logger.info(f"Enabled service: {service_id}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to enable service {service_id}: {e}")
|
|
|
|
async def _disable_service(self, service_id: str) -> None:
|
|
"""Disable a service"""
|
|
try:
|
|
# Unload plugin to free resources
|
|
registry.unload_plugin(service_id)
|
|
logger.info(f"Disabled service: {service_id}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to disable service {service_id}: {e}")
|
|
|
|
async def _update_service(self, service_id: str, config: Dict) -> None:
|
|
"""Update service configuration"""
|
|
# For now, just disable and re-enable
|
|
await self._disable_service(service_id)
|
|
await self._enable_service(service_id, config)
|
|
|
|
async def _validate_hardware_requirements(self, plugin: ServicePlugin, config: Dict) -> None:
|
|
"""Validate that miner meets plugin requirements"""
|
|
requirements = plugin.get_hardware_requirements()
|
|
|
|
# This would check against actual miner hardware
|
|
# For now, just log the requirements
|
|
logger.debug(f"Hardware requirements for {plugin.service_id}: {requirements}")
|
|
|
|
async def _sync_loop(self) -> None:
|
|
"""Background sync loop"""
|
|
while True:
|
|
await asyncio.sleep(self._update_interval)
|
|
await self.sync_services()
|
|
|
|
async def execute_service(self, service_id: str, request: Dict) -> Dict:
|
|
"""Execute a service request"""
|
|
try:
|
|
# Check if service is enabled
|
|
if service_id not in self.enabled_services:
|
|
raise PluginNotFoundError(f"Service {service_id} is not enabled")
|
|
|
|
# Get plugin
|
|
plugin = registry.get_plugin(service_id)
|
|
if not plugin:
|
|
raise PluginNotFoundError(f"No plugin loaded for service: {service_id}")
|
|
|
|
# Execute request
|
|
result = await plugin.execute(request)
|
|
|
|
# Convert result to dict
|
|
return {
|
|
"success": result.success,
|
|
"data": result.data,
|
|
"error": result.error,
|
|
"metrics": result.metrics,
|
|
"execution_time": result.execution_time
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to execute service {service_id}: {e}")
|
|
return {
|
|
"success": False,
|
|
"error": str(e)
|
|
}
|
|
|
|
def get_enabled_services(self) -> List[str]:
|
|
"""Get list of enabled services"""
|
|
return list(self.enabled_services)
|
|
|
|
def get_service_status(self) -> Dict[str, Dict]:
|
|
"""Get status of all services"""
|
|
status = {}
|
|
|
|
for service_id in registry.list_plugins():
|
|
plugin = registry.get_plugin(service_id)
|
|
status[service_id] = {
|
|
"enabled": service_id in self.enabled_services,
|
|
"loaded": plugin is not None,
|
|
"config": self.service_configs.get(service_id, {}),
|
|
"capabilities": plugin.capabilities if plugin else []
|
|
}
|
|
|
|
return status
|
|
|
|
async def health_check(self) -> Dict[str, bool]:
|
|
"""Health check all enabled services"""
|
|
results = {}
|
|
|
|
for service_id in self.enabled_services:
|
|
plugin = registry.get_plugin(service_id)
|
|
if plugin:
|
|
try:
|
|
results[service_id] = await plugin.health_check()
|
|
except Exception as e:
|
|
logger.error(f"Health check failed for {service_id}: {e}")
|
|
results[service_id] = False
|
|
else:
|
|
results[service_id] = False
|
|
|
|
return results
|
|
|
|
async def stop(self) -> None:
|
|
"""Stop the discovery service"""
|
|
logger.info("Stopping service discovery")
|
|
registry.cleanup_all()
|