trustgraph/trustgraph-flow/trustgraph/config/service/service.py
2025-04-15 16:13:18 +01:00

165 lines
4.5 KiB
Python

"""
Config service. Manages system global configuration state
"""
from pulsar.schema import JsonSchema
from trustgraph.schema import ConfigRequest, ConfigResponse, ConfigPush
from trustgraph.schema import Error
from trustgraph.schema import config_request_queue, config_response_queue
from trustgraph.schema import config_push_queue
from trustgraph.log_level import LogLevel
from trustgraph.base import AsyncProcessor, Consumer, Producer
from . config import Configuration
from ... base import ProcessorMetrics, ConsumerMetrics, ProducerMetrics
module = "config-svc"
default_request_queue = config_request_queue
default_response_queue = config_response_queue
default_push_queue = config_push_queue
default_subscriber = module
# This behaves just like a dict, should be easier to add persistent storage
# later
class Processor(AsyncProcessor):
def __init__(self, **params):
request_queue = params.get("request_queue", default_request_queue)
response_queue = params.get("response_queue", default_response_queue)
push_queue = params.get("push_queue", default_push_queue)
subscriber = params.get("subscriber", default_subscriber)
id = params.get("id")
request_schema = ConfigRequest
response_schema = ConfigResponse
push_schema = ConfigResponse
ProcessorMetrics(id=id).info(
{
"subscriber": subscriber,
"request_queue": request_queue,
"request_schema": request_schema.__name__,
"response_queue": response_queue,
"response_schema": request_schema.__name__,
}
)
super(Processor, self).__init__(
**params | {
"request_schema": request_schema.__name__,
"response_schema": response_schema.__name__,
"push_schema": push_schema.__name__,
}
)
self.request_metrics = ConsumerMetrics(id + "-request")
self.response_metrics = ProducerMetrics(id + "-response")
self.push_metrics = ProducerMetrics(id + "-push")
self.push_pub = self.publish(
queue = push_queue,
schema = ConfigPush,
metrics = self.push_metrics,
)
self.response_pub = self.publish(
queue = response_queue,
schema = ConfigResponse,
metrics = self.response_metrics,
)
self.subs = self.subscribe(
queue = request_queue,
subscriber = subscriber,
schema = request_schema,
handler = self.on_message,
metrics = self.request_metrics,
)
self.config = Configuration(self.push)
print("Service initialised.")
async def start(self):
await self.push()
await self.subs.start()
async def push(self):
resp = ConfigPush(
version = self.config.version,
value = None,
directory = None,
values = None,
config = self.config,
error = None,
)
await self.push_pub.send(resp)
print("Pushed version ", self.config.version)
async def on_message(self, msg, consumer):
try:
v = msg.value()
# Sender-produced ID
id = msg.properties()["id"]
print(f"Handling {id}...", flush=True)
resp = await self.config.handle(v)
await self.response_pub.send(resp, properties={"id": id})
consumer.acknowledge(msg)
except Exception as e:
resp = ConfigResponse(
error=Error(
type = "unexpected-error",
message = str(e),
),
text=None,
)
await self.response_pub.send(resp, properties={"id": id})
consumer.acknowledge(msg)
@staticmethod
def add_args(parser):
AsyncProcessor.add_args(parser)
parser.add_argument(
'-q', '--request-queue',
default=default_request_queue,
help=f'Request queue (default: {default_request_queue})'
)
parser.add_argument(
'-r', '--response-queue',
default=default_response_queue,
help=f'Response queue {default_response_queue}',
)
parser.add_argument(
'--push-queue',
default=default_push_queue,
help=f'Config push queue (default: {default_push_queue})'
)
def run():
Processor.launch(module, __doc__)