trustgraph/trustgraph-flow/trustgraph/gateway/requestor.py
cybermaggedon a9197d11ee
Feature/configure flows (#345)
- Keeps processing in different flows separate so that data can go to different stores / collections etc.
- Potentially supports different processing flows
- Tidies the processing API with common base-classes for e.g. LLMs, and automatic configuration of 'clients' to use the right queue names in a flow
2025-04-22 20:21:38 +01:00

99 lines
2.3 KiB
Python

import asyncio
import uuid
import logging
from .. base import Publisher
from .. base import Subscriber
logger = logging.getLogger("requestor")
logger.setLevel(logging.INFO)
class ServiceRequestor:
def __init__(
self,
pulsar_client,
request_queue, request_schema,
response_queue, response_schema,
subscription="api-gateway", consumer_name="api-gateway",
timeout=600,
):
self.pub = Publisher(
pulsar_client, request_queue,
schema=request_schema,
)
self.sub = Subscriber(
pulsar_client, response_queue,
subscription, consumer_name,
response_schema
)
self.timeout = timeout
async def start(self):
await self.pub.start()
await self.sub.start()
def to_request(self, request):
raise RuntimeError("Not defined")
def from_response(self, response):
raise RuntimeError("Not defined")
async def process(self, request, responder=None):
id = str(uuid.uuid4())
try:
q = await self.sub.subscribe(id)
await self.pub.send(id, self.to_request(request))
while True:
try:
resp = await asyncio.wait_for(
q.get(), timeout=self.timeout
)
except Exception as e:
raise RuntimeError("Timeout")
if resp.error:
err = { "error": {
"type": resp.error.type,
"message": resp.error.message,
} }
if responder:
await responder(err, True)
return err
resp, fin = self.from_response(resp)
print(resp, fin)
if responder:
await responder(resp, fin)
if fin:
return resp
except Exception as e:
logging.error(f"Exception: {e}")
err = { "error": {
"type": "gateway-error",
"message": str(e),
} }
if responder:
await responder(err, True)
return err
finally:
await self.sub.unsubscribe(id)