Implemented dispatcher

This commit is contained in:
Cyber MacGeddon 2025-06-23 23:30:43 +01:00
parent 556def3dc0
commit 2f416d5833
2 changed files with 52 additions and 57 deletions

View file

@ -3,16 +3,36 @@ import logging
import uuid import uuid
from typing import Dict, Any, Optional from typing import Dict, Any, Optional
from trustgraph.messaging import TranslatorRegistry from trustgraph.messaging import TranslatorRegistry
from ..gateway.dispatch.manager import DispatcherManager
logger = logging.getLogger("dispatcher") logger = logging.getLogger("dispatcher")
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
class WebSocketResponder:
"""Simple responder that captures response for websocket return"""
def __init__(self):
self.response = None
self.completed = False
async def send(self, data):
"""Capture the response data"""
self.response = data
self.completed = True
class MessageDispatcher: class MessageDispatcher:
def __init__(self, max_workers: int = 10): def __init__(self, max_workers: int = 10, config_receiver=None, pulsar_client=None):
self.max_workers = max_workers self.max_workers = max_workers
self.semaphore = asyncio.Semaphore(max_workers) self.semaphore = asyncio.Semaphore(max_workers)
self.active_tasks = set() self.active_tasks = set()
self.pulsar_client = pulsar_client
# Use DispatcherManager for flow and service management
if pulsar_client and config_receiver:
self.dispatcher_manager = DispatcherManager(pulsar_client, config_receiver)
else:
self.dispatcher_manager = None
logger.warning("No pulsar_client or config_receiver provided - using fallback mode")
# Service name mapping from websocket protocol to translator registry # Service name mapping from websocket protocol to translator registry
self.service_mapping = { self.service_mapping = {
@ -46,38 +66,35 @@ class MessageDispatcher:
request_id = message.get('id', str(uuid.uuid4())) request_id = message.get('id', str(uuid.uuid4()))
service = message.get('service') service = message.get('service')
request_data = message.get('request', {}) request_data = message.get('request', {})
flow_id = message.get('flow', 'default') # Default flow
logger.info(f"Processing message {request_id} for service {service}") logger.info(f"Processing message {request_id} for service {service} on flow {flow_id}")
try: try:
# Map websocket service name to translator service name if not self.dispatcher_manager:
translator_service = self.service_mapping.get(service, service) raise RuntimeError("DispatcherManager not available - pulsar_client and config_receiver required")
# Get the request translator # Use DispatcherManager for flow-based processing
if TranslatorRegistry.has_service(translator_service): responder = WebSocketResponder()
request_translator = TranslatorRegistry.get_request_translator(translator_service)
response_translator = TranslatorRegistry.get_response_translator(translator_service)
# Convert websocket request to Pulsar message # Map websocket service name to dispatcher service name
pulsar_request = request_translator.to_pulsar(request_data) dispatcher_service = self.service_mapping.get(service, service)
logger.info(f"Converted to Pulsar request: {type(pulsar_request)}")
# Send to fixme function (placeholder for actual processing) # Use DispatcherManager to process the request through Pulsar queues
pulsar_response = await self.fixme(pulsar_request) await self.dispatcher_manager.invoke_flow_service(
request_data, responder, flow_id, dispatcher_service
)
# Convert Pulsar response back to websocket format # Get the response from the responder
response_data = response_translator.from_pulsar(pulsar_response) if responder.completed and responder.response:
response_data = responder.response
response = {
'id': request_id,
'response': response_data
}
else: else:
logger.warning(f"No translator found for service: {service}") response_data = {'error': 'No response received'}
response = {
'id': request_id, response = {
'response': {'error': f'Unsupported service: {service}'} 'id': request_id,
} 'response': response_data
}
except Exception as e: except Exception as e:
logger.error(f"Error processing message {request_id}: {e}") logger.error(f"Error processing message {request_id}: {e}")
@ -89,35 +106,11 @@ class MessageDispatcher:
logger.info(f"Completed processing message {request_id}") logger.info(f"Completed processing message {request_id}")
return response return response
async def fixme(self, pulsar_request) -> Any:
"""Placeholder function for actual message processing"""
logger.info(f"FIXME: Processing Pulsar request of type {type(pulsar_request)}")
# Wait 2 seconds as before
await asyncio.sleep(2.0)
# For now, create a mock response based on request type
# This will be replaced with actual processing logic later
request_type = type(pulsar_request).__name__
# Import appropriate response schema - this is a temporary mock
if "TextCompletion" in request_type:
from trustgraph.schema import TextCompletionResponse
return TextCompletionResponse(response="hello world")
elif "Agent" in request_type:
from trustgraph.schema import AgentResponse
return AgentResponse(answer="hello world")
elif "Embeddings" in request_type:
from trustgraph.schema import EmbeddingsResponse
return EmbeddingsResponse(vectors=[[0.1, 0.2, 0.3]])
else:
# Generic response for unknown types
logger.warning(f"Unknown request type: {request_type}")
# Return a simple dict that can be handled
return {"response": "hello world"}
async def shutdown(self): async def shutdown(self):
if self.active_tasks: if self.active_tasks:
logger.info(f"Waiting for {len(self.active_tasks)} active tasks to complete") logger.info(f"Waiting for {len(self.active_tasks)} active tasks to complete")
await asyncio.gather(*self.active_tasks, return_exceptions=True) await asyncio.gather(*self.active_tasks, return_exceptions=True)
# DispatcherManager handles its own cleanup
logger.info("Dispatcher shutdown complete") logger.info("Dispatcher shutdown complete")

View file

@ -23,7 +23,6 @@ class ReverseGateway:
self.max_workers = max_workers self.max_workers = max_workers
self.ws: Optional[ClientWebSocketResponse] = None self.ws: Optional[ClientWebSocketResponse] = None
self.session: Optional[ClientSession] = None self.session: Optional[ClientSession] = None
self.dispatcher = MessageDispatcher(max_workers)
self.running = False self.running = False
self.reconnect_delay = 3.0 self.reconnect_delay = 3.0
@ -48,6 +47,9 @@ class ReverseGateway:
# Initialize config receiver # Initialize config receiver
self.config_receiver = ConfigReceiver(self.pulsar_client) self.config_receiver = ConfigReceiver(self.pulsar_client)
# Initialize dispatcher with config_receiver and pulsar_client - must be created after config_receiver
self.dispatcher = MessageDispatcher(max_workers, self.config_receiver, self.pulsar_client)
async def connect(self) -> bool: async def connect(self) -> bool:
try: try:
if self.session is None: if self.session is None: