Skip to content
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

refactor: reduce duplicate code in run actions #603

Closed
wants to merge 6 commits into from

Conversation

jshimkus-rh
Copy link
Contributor

@jshimkus-rh jshimkus-rh commented Oct 24, 2023

Utilize OO inheritance to reduce code duplicated across the various run actions.

Makes the core of all run actions' __call__ a sequence of pre-process, job start, run and post-process.

Signed-off-by: Joe Shimkus <[email protected]>
Re-establishes a single log message of "Calling Ansible runner" rather than one per iteration.

Signed-off-by: Joe Shimkus <[email protected]>
@jshimkus-rh jshimkus-rh requested a review from a team October 27, 2023 17:20
Copy link
Contributor

@Alex-Izquierdo Alex-Izquierdo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for context: #537 (comment)

@Alex-Izquierdo
Copy link
Contributor

You may want to incorporate the change in #606
as it is a bugfix requested by customer I guess it will be merged before this PR.

@jshimkus-rh
Copy link
Contributor Author

Just for context: #537 (comment)

Thanks. I'd categorize this change as an additional refinement of the run* actions' changes in that PR.

from typing import Callable
from urllib.parse import urljoin

import drools
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jshimkus-rh Do we need to import specific things here maybe?

from drools import ruleset

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jshimkus-rh The earlier implementation tried using a hierarchical model which @benthomasson didn't want to use and wanted to use composition instead of inheritance, this PR seems to be going using inheritance. So we would need approval from @benthomasson if we wants to use inheritance here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming such an objection from @benthomasson I'd like to hear what he considers to be compositional as there's nothing in the previous code (being changed with this PR) that adheres to the conventional definition of composition; there's no facility being re-used across the various classes, rather there's largely duplicated code implemented separately.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jshimkus-rh Do we need to import specific things here maybe?


from drools import ruleset

We could do that. I chose not to in order to limit possible confusion between drools and EDA's concept of rulesets.

It was motivated by consistency with eliminating the transitive overriding in tests of the drools apis which would have to be specified against run_base.py file rather than the run_job_template file, as an example.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My two cents: From what I understand, composition, whether in contrast to inheritance or not, is a pattern used to decouple pieces of logic or distinct responsibilities. In this scenario, where we have shared logic across similar actions, inheritance seems like a fitting approach to me.

Alex-Izquierdo
Alex-Izquierdo previously approved these changes Oct 30, 2023
)
await super().__call__()

async def _do_run(self) -> bool:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't actually need a boolean as result here and I think it is not a good pattern. Error handling should be done through exceptions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have a binary situation; we have success, retriable errors and non-retriable errors. I find I can live with the idea of using StopAsyncIteration and have pushed a change with that. If people would rather have a specific exception for the hierarchy let me know.

@Alex-Izquierdo Alex-Izquierdo self-requested a review October 30, 2023 16:51
@benthomasson
Copy link
Contributor

benthomasson commented Nov 1, 2023

Actions will become plugins in a future release. My main concern here is that the actions have a minimal interface with few dependencies and are easy to write by third-party developers. Our style for these plugins is to have a single file that defines the plugin where the interface resides. Here run_base breaks that convention by hiding the interface in another file. run_job_template.py and run_workflow_template.py do have a lot of shared code.

@benthomasson
Copy link
Contributor

I prefer to use inheritance only for is-a relationships and not for code reuse. Library functions are good for code reuse. Here we only have two examples run_job_template.py and run_workflow_template.py which is not enough examples to make good abstractions yet. I prefer a minimum of 3 examples. We should resist the temptation to make abstractions too early. I am fine with leaving the duplicate code as is until we have more examples of how we could abstract it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants