-
Notifications
You must be signed in to change notification settings - Fork 451
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes #6360: Optional dependency on REST manager in components #6381
Conversation
e0bcd15
to
baa21ce
Compare
retest this please |
1 similar comment
retest this please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I appreciate your care about developers in terms of "encapsulating logic to a base class" and simplifying the code of components.
I am just afraid that it adds cognitive complexity to the components themselves.
Now operations with REST are not as obvious as they were before.
I would suggest just making a dependency of RESTComponent
optional (with adding the corresponding code) without incapsulating it in a base class.
src/tribler-core/tribler_core/components/bandwidth_accounting/bandwidth_accounting_component.py
Show resolved
Hide resolved
@drew2a in general I agree that inheritance adds some cognitive complexity, and try to avoid using it. But in this specific case I think that having the logic of endpoint initialization repeated in many components is a bit cumbersome for the following reason:
For example, this fragment of TunnelComponent initialization code needs to check the endpoints availability: rest_component = await self.get_component(RESTComponent)
if rest_component:
rest_component.rest_manager.get_endpoint('ipv8').endpoints['/tunnel'].initialize(self._ipv8)
if download_component:
rest_component.rest_manager.get_endpoint('downloads').tunnel_community = community
debug_endpoint = rest_component.rest_manager.get_endpoint('debug')
debug_endpoint.tunnel_community = community Now it looks like this: await self.init_endpoints(['downloads', 'debug'], [('tunnel_community', community)])
await self.init_ipv8_endpoints(self._ipv8, ['tunnel']) In my opinion, providing reusable methods for endpoint initialization makes the remaining code of components easier to understand. |
050a026
to
df02aff
Compare
retest this please |
df02aff
to
a449b88
Compare
…ponent.init_endpoints()
@kozlovsky you are right, agree. By the way, to increase readability we may use named arguments, eg: await self.init_endpoints(endpoints = ['downloads', 'debug'], values = [('tunnel_community', community)])
await self.init_ipv8_endpoints(self._ipv8, endpoints = ['tunnel']) or even use a dict instead a list of tules: await self.init_endpoints(endpoints = ['downloads', 'debug'], values = {'tunnel_community': community})
await self.init_ipv8_endpoints(self._ipv8, endpoints = ['tunnel']) |
a449b88
to
cfef5e1
Compare
@drew2a is right. Just use a single, dict argument. |
Kudos, SonarCloud Quality Gate passed! 0 Bugs No Coverage information |
This PR makes the dependency of components on REST manager optional. It adds a base class
RestfulComponent
, which provides three methods:The
init_endpoints
method simplifies endpoint initialization and can be used inside a component'srun
method to inject values to REST endpoints:The method sets specified attributes to all enlisted endpoints. If RESTComponent or some specific endpoint is not available, it just skipped silently.
It also is possible to initialize
ipv8
endpoints as well by specifying theipv8
instance.This way it becomes not necessary to explicitly access RESTComponent and REST endpoints in a component's code.
The
shutdown
method of RestfulComponent will release endpoints by replacing previously set values toNone
:The
set_readable_status
abstracts out the setting Tribler user-readable status to a specific value.