Merge in RR/pyinfra from RED-6273-multi-tenant-storage to master
Squashed commit of the following:
commit 0fead1f8b59c9187330879b4e48d48355885c27c
Author: Julius Unverfehrt <julius.unverfehrt@iqser.com>
Date: Tue Mar 28 15:02:22 2023 +0200
fix typos
commit 892a803726946876f8b8cd7905a0e73c419b2fb1
Author: Matthias Bisping <matthias.bisping@axbit.com>
Date: Tue Mar 28 14:41:49 2023 +0200
Refactoring
Replace custom storage caching logic with LRU decorator
commit eafcd90260731e3360ce960571f07dee8f521327
Author: Julius Unverfehrt <julius.unverfehrt@iqser.com>
Date: Fri Mar 24 12:50:13 2023 +0100
fix bug in storage connection from endpoint
commit d0c9fb5b7d1c55ae2f90e8faa1efec9f7587c26a
Author: Julius Unverfehrt <julius.unverfehrt@iqser.com>
Date: Fri Mar 24 11:49:34 2023 +0100
add logs to PayloadProcessor
- set log messages to determine if x-tenant
storage connection is working
commit 97309fe58037b90469cf7a3de342d4749a0edfde
Author: Julius Unverfehrt <julius.unverfehrt@iqser.com>
Date: Fri Mar 24 10:41:59 2023 +0100
update PayloadProcessor
- introduce storage cache to make every unique
storage connection only once
- add functionality to pass optional processing
kwargs in queue message like the operation key to
the processing function
commit d48e8108fdc0d463c89aaa0d672061ab7dca83a0
Author: Julius Unverfehrt <julius.unverfehrt@iqser.com>
Date: Wed Mar 22 13:34:43 2023 +0100
add multi-tenant storage connection 1st iteration
- forward x-tenant-id from queue message header to
payload processor
- add functions to receive storage infos from an
endpoint or the config. This enables hashing and
caching of connections created from these infos
- add function to initialize storage connections
from storage infos
- streamline and refactor tests to make them more
readable and robust and to make it easier to add
new tests
- update payload processor with first iteration
of multi tenancy storage connection support
with connection caching and backwards compability
commit 52c047c47b98e62d0b834a9b9b6c0e2bb0db41e5
Author: Julius Unverfehrt <julius.unverfehrt@iqser.com>
Date: Tue Mar 21 15:35:57 2023 +0100
add AES/GCM cipher functions
- decrypt x-tenant storage connection strings
99 lines
3.8 KiB
Python
99 lines
3.8 KiB
Python
from dataclasses import dataclass
|
|
from itertools import chain
|
|
from operator import itemgetter
|
|
from typing import Union, Sized
|
|
|
|
from funcy import project
|
|
|
|
from pyinfra.config import Config
|
|
from pyinfra.utils.file_extension_parsing import make_file_extension_parser
|
|
|
|
|
|
@dataclass
|
|
class QueueMessagePayload:
|
|
dossier_id: str
|
|
file_id: str
|
|
x_tenant_id: Union[str, None]
|
|
|
|
target_file_extension: str
|
|
response_file_extension: str
|
|
|
|
target_file_type: Union[str, None]
|
|
target_compression_type: Union[str, None]
|
|
response_file_type: Union[str, None]
|
|
response_compression_type: Union[str, None]
|
|
|
|
target_file_name: str
|
|
response_file_name: str
|
|
|
|
processing_kwargs: dict
|
|
|
|
|
|
class QueueMessagePayloadParser:
|
|
def __init__(self, file_extension_parser, allowed_processing_args=("operation",)):
|
|
self.parse_file_extensions = file_extension_parser
|
|
self.allowed_args = allowed_processing_args
|
|
|
|
def __call__(self, payload: dict) -> QueueMessagePayload:
|
|
"""Translate the queue message payload to the internal QueueMessagePayload object."""
|
|
return self._parse_queue_message_payload(payload)
|
|
|
|
def _parse_queue_message_payload(self, payload: dict) -> QueueMessagePayload:
|
|
dossier_id, file_id, target_file_extension, response_file_extension = itemgetter(
|
|
"dossierId", "fileId", "targetFileExtension", "responseFileExtension"
|
|
)(payload)
|
|
x_tenant_id = payload.get("X-TENANT-ID")
|
|
|
|
target_file_type, target_compression_type, response_file_type, response_compression_type = chain.from_iterable(
|
|
map(self.parse_file_extensions, [target_file_extension, response_file_extension])
|
|
)
|
|
|
|
target_file_name = f"{dossier_id}/{file_id}.{target_file_extension}"
|
|
response_file_name = f"{dossier_id}/{file_id}.{response_file_extension}"
|
|
|
|
processing_kwargs = project(payload, self.allowed_args)
|
|
|
|
return QueueMessagePayload(
|
|
dossier_id=dossier_id,
|
|
file_id=file_id,
|
|
x_tenant_id=x_tenant_id,
|
|
target_file_extension=target_file_extension,
|
|
response_file_extension=response_file_extension,
|
|
target_file_type=target_file_type,
|
|
target_compression_type=target_compression_type,
|
|
response_file_type=response_file_type,
|
|
response_compression_type=response_compression_type,
|
|
target_file_name=target_file_name,
|
|
response_file_name=response_file_name,
|
|
processing_kwargs=processing_kwargs,
|
|
)
|
|
|
|
|
|
def get_queue_message_payload_parser(config: Config) -> QueueMessagePayloadParser:
|
|
file_extension_parser = make_file_extension_parser(config.allowed_file_types, config.allowed_compression_types)
|
|
return QueueMessagePayloadParser(file_extension_parser)
|
|
|
|
|
|
class QueueMessagePayloadFormatter:
|
|
@staticmethod
|
|
def format_service_processing_result_for_storage(
|
|
queue_message_payload: QueueMessagePayload, service_processing_result: Sized
|
|
) -> dict:
|
|
"""Format the results of a processing function with the QueueMessagePayload for the storage upload."""
|
|
return {
|
|
"dossierId": queue_message_payload.dossier_id,
|
|
"fileId": queue_message_payload.file_id,
|
|
"targetFileExtension": queue_message_payload.target_file_extension,
|
|
"responseFileExtension": queue_message_payload.response_file_extension,
|
|
"data": service_processing_result,
|
|
}
|
|
|
|
@staticmethod
|
|
def format_to_queue_message_response_body(queue_message_payload: QueueMessagePayload) -> dict:
|
|
"""Format QueueMessagePayload for the AMPQ response after processing."""
|
|
return {"dossierId": queue_message_payload.dossier_id, "fileId": queue_message_payload.file_id}
|
|
|
|
|
|
def get_queue_message_payload_formatter() -> QueueMessagePayloadFormatter:
|
|
return QueueMessagePayloadFormatter()
|