73 lines
2.4 KiB
Python
73 lines
2.4 KiB
Python
import re
|
|
from typing import Optional, Set
|
|
|
|
from amqp.adapter.logging_utils import logging_info
|
|
from amqp.model.model import AMQRoute
|
|
from amqp.router.utils import sanitize_as_rabbitmq_name
|
|
|
|
|
|
class RouteDatabase:
|
|
def __init__(self):
|
|
self.routes: Set[AMQRoute] = set()
|
|
|
|
def get_routes(self) -> Set[AMQRoute]:
|
|
return self.routes
|
|
|
|
def pattern(self, routing_key: str) -> re.Pattern:
|
|
breaker = False
|
|
tokens = routing_key.split(".")
|
|
counter = len(tokens)
|
|
regex_parts = []
|
|
|
|
for token in tokens:
|
|
counter -= 1
|
|
if not breaker:
|
|
if token == "":
|
|
res = "[^\\.]*"
|
|
elif token == "#":
|
|
breaker = True
|
|
res = ".*$"
|
|
else:
|
|
res = token
|
|
if counter > 0 and not breaker:
|
|
res += "\\."
|
|
regex_parts.append(res)
|
|
else:
|
|
regex_parts.append("")
|
|
|
|
regex = "".join(filter(lambda x: x != "", regex_parts))
|
|
if not routing_key:
|
|
return re.compile(".*")
|
|
return re.compile(regex)
|
|
|
|
def matches(self, routing_key_from_route: str, routing_key_from_message: str) -> bool:
|
|
route_pattern = self.pattern(routing_key_from_route)
|
|
return bool(route_pattern.match(sanitize_as_rabbitmq_name(routing_key_from_message)))
|
|
|
|
def wrap_routes(self) -> str:
|
|
return ",".join(str(route) for route in self.routes)
|
|
|
|
def find_route(self, domain: str, path: str) -> AMQRoute | None:
|
|
routing_key = sanitize_as_rabbitmq_name(f"{domain}.{path}")
|
|
logging_info(f"findRoute key:{routing_key} in:{self.wrap_routes()}")
|
|
for route in self.routes:
|
|
if self.matches(route.key, routing_key):
|
|
return route
|
|
return None
|
|
|
|
def find_route_by_service(self, service_name: str) -> Optional[AMQRoute]:
|
|
logging_info(f"findRoute service_name:{service_name} in:{self.wrap_routes()}")
|
|
for route in self.routes:
|
|
if route.component_name == service_name:
|
|
return route
|
|
return None
|
|
|
|
def add_route(self, route: AMQRoute) -> bool:
|
|
if route not in self.routes:
|
|
self.routes.add(route)
|
|
return True
|
|
return False
|
|
|
|
def remove_route(self, route: AMQRoute) -> bool:
|
|
return route in self.routes and self.routes.remove(route)
|