From 30b5724343588606a7e13ef8c9e762dcecb47ab0 Mon Sep 17 00:00:00 2001 From: AnneY Date: Tue, 3 Jan 2023 20:42:51 +0800 Subject: [PATCH 1/3] fix: ignore uncopyable attribute --- jina/helper.py | 20 +++++++++++++++++++ .../runtimes/gateway/composite/gateway.py | 6 ++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/jina/helper.py b/jina/helper.py index 73695148648fc..0a857a204cf2b 100644 --- a/jina/helper.py +++ b/jina/helper.py @@ -54,6 +54,7 @@ 'get_public_ip', 'get_internal_ip', 'convert_tuple_to_list', + 'deepcopy_with_ignore_attrs', 'run_async', 'deprecated_alias', 'retry', @@ -1265,6 +1266,25 @@ def convert_tuple_to_list(d: Dict): convert_tuple_to_list(v) +def deepcopy_with_ignore_attrs( + obj: Any, ignore_attrs: List[str] +) -> Any: + """Deep copy an object and ignore some attributes + + :param obj: the object to copy + :param ignore_attrs: the attributes to ignore + :return: the copied object + """ + import copy + + memo = {} + for k in ignore_attrs: + if hasattr(obj, k): + memo[id(getattr(obj, k))] = None # getattr(obj, k) + + return copy.deepcopy(obj, memo) + + def is_jupyter() -> bool: # pragma: no cover """ Check if we're running in a Jupyter notebook, using magic command `get_ipython` that only available in Jupyter. diff --git a/jina/serve/runtimes/gateway/composite/gateway.py b/jina/serve/runtimes/gateway/composite/gateway.py index b93458f9477c0..478de983262f1 100644 --- a/jina/serve/runtimes/gateway/composite/gateway.py +++ b/jina/serve/runtimes/gateway/composite/gateway.py @@ -1,6 +1,7 @@ import copy from typing import List, Optional +from jina.helper import deepcopy_with_ignore_attrs from jina.serve.gateway import BaseGateway @@ -21,10 +22,11 @@ def __init__( self.gateways: List[BaseGateway] = [] for port, protocol in zip(self.ports, self.protocols): gateway_cls = _get_gateway_class(protocol) - runtime_args = copy.deepcopy(self.runtime_args) + # ignore metrics_registry since it is not copyable + runtime_args = deepcopy_with_ignore_attrs(self.runtime_args, ['metrics_registry']) runtime_args.port = [port] runtime_args.protocol = [protocol] - gateway_kwargs = copy.deepcopy(kwargs) + gateway_kwargs = {k: v for k, v in kwargs.items() if k != 'runtime_args'} gateway_kwargs['runtime_args'] = dict(vars(runtime_args)) gateway = gateway_cls(**gateway_kwargs) self.gateways.append(gateway) From 2af7dcbee25403d5b8a684dd8ad2bce782602fae Mon Sep 17 00:00:00 2001 From: AnneY Date: Tue, 3 Jan 2023 20:43:24 +0800 Subject: [PATCH 2/3] test: add test for multiprotocol with monitoring --- .../flow/flow-construct/test_flow_multiprotocol.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/unit/orchestrate/flow/flow-construct/test_flow_multiprotocol.py b/tests/unit/orchestrate/flow/flow-construct/test_flow_multiprotocol.py index 9dbfaf4f99b64..4b7656357c3c6 100644 --- a/tests/unit/orchestrate/flow/flow-construct/test_flow_multiprotocol.py +++ b/tests/unit/orchestrate/flow/flow-construct/test_flow_multiprotocol.py @@ -118,3 +118,14 @@ def test_flow_multiprotocol_ports_protocols_mismatch(): 'You need to specify as much protocols as ports if you want to use a jina built-in gateway' in err_info.value.args[0] ) + + +def test_flow_multiprotocol_with_monitoring(): + ports = [random_port(), random_port(), random_port()] + protocols = PROTOCOLS + flow = Flow().config_gateway(port=ports, protocol=protocols, monitoring=True) + + with flow: + for port, protocol in zip(ports, protocols): + client = Client(port=port, protocol=protocol) + client.post('/', inputs=[Document()]) From a28f96a0475e64b958696f3d57bb188f21886cae Mon Sep 17 00:00:00 2001 From: AnneY Date: Tue, 3 Jan 2023 22:22:53 +0800 Subject: [PATCH 3/3] refactor: change deepcopy to private --- jina/helper.py | 20 ---------------- .../runtimes/gateway/composite/gateway.py | 23 ++++++++++++++++--- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/jina/helper.py b/jina/helper.py index 0a857a204cf2b..73695148648fc 100644 --- a/jina/helper.py +++ b/jina/helper.py @@ -54,7 +54,6 @@ 'get_public_ip', 'get_internal_ip', 'convert_tuple_to_list', - 'deepcopy_with_ignore_attrs', 'run_async', 'deprecated_alias', 'retry', @@ -1266,25 +1265,6 @@ def convert_tuple_to_list(d: Dict): convert_tuple_to_list(v) -def deepcopy_with_ignore_attrs( - obj: Any, ignore_attrs: List[str] -) -> Any: - """Deep copy an object and ignore some attributes - - :param obj: the object to copy - :param ignore_attrs: the attributes to ignore - :return: the copied object - """ - import copy - - memo = {} - for k in ignore_attrs: - if hasattr(obj, k): - memo[id(getattr(obj, k))] = None # getattr(obj, k) - - return copy.deepcopy(obj, memo) - - def is_jupyter() -> bool: # pragma: no cover """ Check if we're running in a Jupyter notebook, using magic command `get_ipython` that only available in Jupyter. diff --git a/jina/serve/runtimes/gateway/composite/gateway.py b/jina/serve/runtimes/gateway/composite/gateway.py index 478de983262f1..feece8a5debaa 100644 --- a/jina/serve/runtimes/gateway/composite/gateway.py +++ b/jina/serve/runtimes/gateway/composite/gateway.py @@ -1,7 +1,6 @@ import copy -from typing import List, Optional +from typing import Any, List, Optional -from jina.helper import deepcopy_with_ignore_attrs from jina.serve.gateway import BaseGateway @@ -23,7 +22,9 @@ def __init__( for port, protocol in zip(self.ports, self.protocols): gateway_cls = _get_gateway_class(protocol) # ignore metrics_registry since it is not copyable - runtime_args = deepcopy_with_ignore_attrs(self.runtime_args, ['metrics_registry']) + runtime_args = self._deepcopy_with_ignore_attrs( + self.runtime_args, ['metrics_registry'] + ) runtime_args.port = [port] runtime_args.protocol = [protocol] gateway_kwargs = {k: v for k, v in kwargs.items() if k != 'runtime_args'} @@ -48,6 +49,22 @@ async def run_server(self): for gateway in self.gateways: await gateway.run_server() + @staticmethod + def _deepcopy_with_ignore_attrs(obj: Any, ignore_attrs: List[str]) -> Any: + """Deep copy an object and ignore some attributes + + :param obj: the object to copy + :param ignore_attrs: the attributes to ignore + :return: the copied object + """ + + memo = {} + for k in ignore_attrs: + if hasattr(obj, k): + memo[id(getattr(obj, k))] = None # getattr(obj, k) + + return copy.deepcopy(obj, memo) + @property def _should_exit(self) -> bool: should_exit_values = [