Added support for file download

This commit is contained in:
Stanislav Hejny
2025-04-09 19:23:26 +01:00
parent 6b420dee0a
commit 113dd38106
16 changed files with 250 additions and 185 deletions
+5 -5
View File
@@ -36,13 +36,13 @@ class RouterConsumer(RouterProducer):
if self.is_open(_channel):
try:
# 1. declare a Queue to receive the RoutingData requests
cm_request_queue: str = self.amq_configuration.amq_adapter.adapter_prefix() + CM_C_REQ_QUEUE
queue: AbstractRobustQueue = await self.channel.declare_queue(name=cm_request_queue, durable=True, exclusive=False, auto_delete=False)
_cm_request_queue: str = self.amq_configuration.amq_adapter.adapter_prefix() + CM_C_REQ_QUEUE
_queue: AbstractRobustQueue = await self.channel.declare_queue(name=_cm_request_queue, durable=True, exclusive=False, auto_delete=False)
# 1a. bind queue to CM_REQUEST_EXCHANGE w/o any conditions (empty routing key)
await queue.bind(exchange=CM_REQUEST_EXCHANGE, routing_key="")
await _queue.bind(exchange=CM_REQUEST_EXCHANGE, routing_key="")
# 1b. Service adapter mode - listens on Request queue and replies to Response queue
logging.info(" [*] RouterConsumer listens for RouteDataRequests on: %s", cm_request_queue)
await queue.consume(callback=self.handle_routing_data_request_message, no_ack=False)
_c_tag = await _queue.consume(callback=self.handle_routing_data_request_message, no_ack=False)
logging.info(" [%s] RouterConsumer listens for RouteDataRequests on: %s", _c_tag, _cm_request_queue)
except Exception as ioe:
logging.error(" [E] RouterConsumer FATAL: cannot initialize, %s", ioe)
else:
+7 -7
View File
@@ -65,16 +65,16 @@ class RouterProducer(RouterBase):
name=CM_RESPONSE_EXCHANGE, type=ExchangeType.fanout
)
# 2a. declare a Response queue for Routing Data replies from Services
cm_response_queue: str = self.get_response_queue_name()
response_queue: AbstractRobustQueue = await self.channel.declare_queue(
name=cm_response_queue, durable=True, exclusive=False, auto_delete=False,
_cm_response_queue: str = self.get_response_queue_name()
_response_queue: AbstractRobustQueue = await self.channel.declare_queue(
name=_cm_response_queue, durable=True, exclusive=False, auto_delete=False,
arguments={}
)
# 2b. bind queue to CM_RESPONSE_EXCHANGE w/o any conditions (empty routing key)
await response_queue.bind(exchange=CM_RESPONSE_EXCHANGE, routing_key="#")
await _response_queue.bind(exchange=CM_RESPONSE_EXCHANGE, routing_key="#")
# 2c. listen for incoming RoutingData messages
await response_queue.consume(callback=self.handle_routing_data_message, no_ack=False)
logging.info(" [*] Routing master listens for Route updates on %s", cm_response_queue)
_c_tag = await _response_queue.consume(callback=self.handle_routing_data_message, no_ack=False)
logging.info(" [%s] Routing master listens for Route updates on %s", _c_tag, _cm_response_queue)
except Exception as ioe:
logging.error(" [E] RouterProducer FATAL: cannot initialize, %s", ioe)
@@ -92,7 +92,7 @@ class RouterProducer(RouterBase):
delivery.getEnvelope().getDeliveryTag(),
delivery.getEnvelope().toString(), str(delivery.getBody()))
"""
# ACK message now so that it is not being redelivered
logging.info(" [%s] ACK message now so that it is not being redelivered", message.delivery_tag)
await message.ack(multiple=False)
cm_message: ServiceMessage = self.service_message_factory.from_bytes(message.body)
# ignore the message if it comes from ourselves (even if from different instance)
-65
View File
@@ -1,65 +0,0 @@
"""
Helper functions used to aid with (de)serialization of messages sent over AMQP.
"""
import struct
from io import BytesIO
from typing import List, Union, Dict
def long_to_bytes(x: int) -> bytes:
return struct.pack('q', x)
def bytes_to_long(b: bytes) -> int:
return struct.unpack('q', b)[0]
def read_long(bis: BytesIO) -> int:
try:
return struct.unpack('q', bis.read(8))[0]
except IOError:
return 0
def object_or_list_as_string(value: Union[str, List[str]]) -> str:
if isinstance(value, list):
return f"[{','.join(value)}]"
return str(value)
def map_as_string(map_: Dict[str, str]) -> str:
return ','.join(f"{k}={object_or_list_as_string(v)}" for k, v in map_.items())
def map_with_list_as_string(map_: Dict[str, List[str]]) -> str:
return ','.join(f"{k}={object_or_list_as_string(v)}" for k, v in map_.items())
def parse_map_string(input_str: str) -> Dict[str, str]:
map_ = {}
if input_str.startswith('{') and input_str.endswith('}'):
for entry in input_str[1:-1].split(','):
if len(entry) > 1:
key, value = entry.split('=')
map_[key] = value
return map_
def csv_as_list(input_str: str) -> List[str]:
return [item.strip() for item in input_str.strip('[]').split(',')]
def add_to_map(map_: Dict[str, List[str]], token: str) -> None:
eq_idx = token.index('=')
if eq_idx > 0:
key = token[:eq_idx]
map_[key] = csv_as_list(token[eq_idx+1:])
def parse_map_list_string(input_str: str) -> Dict[str, List[str]]:
map_ = {}
if input_str.startswith('{') and input_str.endswith('}'):
for token in input_str[1:-1].split('],'):
add_to_map(map_, token)
return map_