def test_configure_depedencies(self): ref1 = "AAA" ref2 = "BBB" refs = References.from_tuples( "Reference1", ref1, Descriptor("pip-services-commons", "reference", "object", "ref2", "1.0"), ref2) config = ConfigParams.from_tuples( "dependencies.ref1", "Reference1", "dependencies.ref2", "pip-services-commons:reference:*:*:*", "dependencies.ref3", None) resolver = DependencyResolver(config) resolver.set_references(refs) assert ref1 == resolver.get_one_required("ref1") assert ref2 == resolver.get_one_required("ref2") assert None == resolver.get_one_optional("ref3")
class DirectClient(IConfigurable, IReferenceable, IOpenable): """ Abstract client that calls controller directly in the same memory space. It is used when multiple microservices are deployed in a single container (monolyth) and communication between them can be done by direct calls rather then through the network. ### Configuration parameters ### - dependencies: - controller: override controller descriptor ### References ### - *:logger:*:*:1.0 (optional) ILogger components to pass log messages - *:counters:*:*:1.0 (optional) ICounters components to pass collected measurements - *:controller:*:*:1.0 controller to call business methods Example: class MyDirectClient(DirectClient, IMyClient): def __init__(self): super(MyDirectClient, self).__init__() self._dependencyResolver.put('controller', Descriptor("mygroup", "controller", "*", "*", "*")) ... def get_data(self, correlation_id, id): timing = self.instrument(correlationId, 'myclient.get_data') result = self._controller.get_data(correlationId, id) timing.end_timing() return result client = MyDirectClient() client.set_references(References.from_tuples(Descriptor("mygroup","controller","default","default","1.0"), controller)) data = client.get_data("123", "1") ... """ _controller = None _opened = True _logger = None _counters = None _dependency_resolver = None def __init__(self): """ Creates a new instance of the client. """ self._logger = CompositeLogger() self._counters = CompositeCounters() self._dependency_resolver = DependencyResolver() self._dependency_resolver.put('controller', 'none') def configure(self, config): """ Configures component by passing configuration parameters. :param config: configuration parameters to be set. """ self._dependency_resolver.configure(config) def set_references(self, references): """ Sets references to dependent components. :param references: references to locate the component dependencies. """ self._logger.set_references(references) self._counters.set_references(references) self._dependency_resolver.set_references(references) self._controller = self._dependency_resolver.get_one_required('controller') def _instrument(self, correlation_id, name): """ Adds instrumentation to log calls and measure call time. It returns a Timing object that is used to end the time measurement. :param correlation_id: (optional) transaction id to trace execution through call chain. :param name: a method name. :return: Timing object to end the time measurement. """ self._logger.trace(correlation_id, f"Executing {name} method") return self._counters.begin_timing(f"{name} .call_time") def _instrument_error(self, correlation_id, name, err, result, callback): """ Adds instrumentation to error handling. :param correlation_id: (optional) transaction id to trace execution through call chain. :param name: a method name. :param err: an occured error :param result: (optional) an execution result :param callback: (optional) an execution callback """ if err is not None: self._logger.error(correlation_id, err, f'Failed to call {name} method') self._counters.increment_one(f"{name}.call_errors") if callback: callback(err, result) def is_opened(self): """ Checks if the component is opened. :return: true if the component has been opened and false otherwise. """ return self._opened def open(self, correlation_id): """ Opens the component. :param correlation_id: (optional) transaction id to trace execution through call chain. """ if self._opened: return if self._controller is None: raise ConnectionException(correlation_id, 'NO_CONTROLLER', 'Controller references is missing') self._opened = True self._logger.info(correlation_id, 'Opened direct client') def close(self, correlation_id): """ Closes component and frees used resources. :param correlation_id: (optional) transaction id to trace execution through call chain. """ if self._opened: self._logger.info(correlation_id, 'Closed direct client') self._opened = False