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 Game Management #283

Merged
merged 32 commits into from
Apr 6, 2023
Merged

Conversation

techman83
Copy link
Member

@techman83 techman83 commented Mar 4, 2023

This is a refactor of the game management to introduce Multi Game support. Whilst there are a large number of lines added, about a 1/3 are test cases and of the code changed, there is now 79% coverage and increased overall coverage from 54% to 67%.

The configuration uses the multi var Click option to achieve the multi game config, which is done via --option var --option var2 or a space separated env var OPTION=var var. This allows a configuration of game=variable, ie ksp=CKANmeta

Out of Scope for this PR

It was already looking like a large set of changes, so some decisions were made to at least constrain it somewhat. Allowing to at least ensure the status quo is working before iterating to the next set of changes

  • Mirrorer - The intention would be to use the generic queue implementation, bringing us to a single queue implementation. However we can't apply for a collection until we have 50 mods to upload.
  • Primary branch from master to main - this seemed sensible to refactor independently
  • Scheduler/Freezer etc to iterate through available games
  • Common/SharedArgs naming convention - this could use improvement. Beyond the entry point, the rest of the application probably doesn't need to care about the arguments, just that they are available. With some more test coverage this could be refactored separately to this PR
  • ModStatus + how we handle identifying/separating of the games

Added

  • Coverage Reporting
  • Game class, that returns game specific values. There is scope here for improvement, but the current implementation does work and will benefit from being used
  • game-id option - this allows the existing utilities to operate as is without much change
  • inflation-queues option - This is a multi var to direct inflation to the relevant queues
  • BaseMessageHandler to provide a consistent interface for handling SQS messages
  • QueueHandler move queue logic out of cli, and into a testable common class

Changed

  • ckanmeta-remote -> ckanmeta-remotes - multi game repos ckanmeta
  • netkan-remote -> netkan-remotes - multi game repos for netkan
  • ia-collection -> ia-collections - allow for the configuration of multi game internet archive repos
  • GitHubPR - repo changed to lazy load, avoiding it trying to auth unnecessarily on class instantiation.
  • SpaceDockAdder moved to common queue/message handler
  • Webhooks multi-game handling
  • Webhooks queues changed to lazy load - speeds up service start and simplifies testing

Improved

  • SharedArgs variables now typed at a class level and not set during init. Improves type hints during coding, and reduces likelihood of a null where it's not expected
  • Boto3 type checking via mypy-boto3 - caveat of it needing if TYPE_CHECKING: to avoid upsetting pylint

Note: Merging will need to coincide with deployment of the updated configuration. I will allocate time to do this, and monitor/test relevant services after.

@HebaruSan
Copy link
Member

SpaceDock is just about ready now (see KSP-SpaceDock/SpaceDock#480). Is there anything still missing from this, or could we merge it and fix things as they break?

netkan/netkan/common.py Outdated Show resolved Hide resolved
netkan/netkan/common.py Outdated Show resolved Hide resolved
netkan/netkan/common.py Outdated Show resolved Hide resolved
netkan/netkan/indexer.py Outdated Show resolved Hide resolved
netkan/netkan/indexer.py Outdated Show resolved Hide resolved
Copy link
Member

@HebaruSan HebaruSan left a comment

Choose a reason for hiding this comment

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

Added some comments.

In addition, a few things are unavoidable for me:

  • This is a LOT of new code, and new code means new bugs (and a lot of review time)
  • The existing code has been made a LOT more complex (increased complexity also means new bugs as well as harder-to-fix bugs)
  • These containers simply don't need to and shouldn't know what game they're operating on; the only behavior that it determines is which repos and queues to use, which was already well handled by the previously existing structure. Everything else they do is the exact same logic regardless of what game it is, so passing around Game objects and game_id values is pure cost in terms of technical debt and cognitive load for no benefit (asterisk for webhooks).
  • It's been almost three weeks and this PR isn't even out of draft status yet (not a criticism of you, but it is a reflection of the contrast between the scope of this design and our available resources)

I'm having second thoughts about closing #282 now that I've seen the details of this code I'm potentially going to have to co-maintain going forward. We probably could have wrapped that one up in another day or two of dev on the webhooks and gone live with KSP2 support weeks ago. Is there anything I can say to persuade you to consider the approach that leverages proven, stable code?

This is a working example of how we could support multiple games
Updated the variables to more accurately reflect they contain multiple vars
netkan/netkan/common.py Outdated Show resolved Hide resolved
@HebaruSan
Copy link
Member

HebaruSan commented Mar 30, 2023

However the queue handling [...] had three different implementations.

Yeah, that was very much intentional. Retrieving messages from a queue and deleting them is, frankly, too simple of a task to be worth centralizing. (To me it's a bit like making a wrapper around
logging.error to reduce the number of "implementations" of logging an error message; doing the thing itself instead is simpler and more maintainable.) Especially when it means that key logic that I need to read to understand what it's doing and investigate/fix bugs is now spread across multiple different files and classes rather than in a simple "X then Y then Z" procedural code block.

We're down to 2

... so naturally I'm not delighted about this. ☝️

netkan/netkan/common.py Outdated Show resolved Hide resolved
netkan/netkan/common.py Outdated Show resolved Hide resolved
netkan/netkan/common.py Outdated Show resolved Hide resolved
netkan/netkan/common.py Outdated Show resolved Hide resolved
Copy link
Member

@HebaruSan HebaruSan left a comment

Choose a reason for hiding this comment

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

Added some replies to previous comments, then tried to figure out how the SpaceDockAdder works now, which led me down the rabbit hole of "when is game getting set," which was confusing because game might be a str or a Game depending on context. Added suggestions for those.

This updates the game to game_id, making it more consistent throughout
the codebase

Co-authored-by: HebaruSan <HebaruSan@users.noreply.github.com>
This moves the queue handling out of common into a more relevantly named section of the codebase.
@techman83
Copy link
Member Author

techman83 commented Mar 31, 2023

Yeah, that was very much intentional. Retrieving messages from a queue and deleting them is, frankly, too simple of a task to be worth centralizing. (To me it's a bit like making a wrapper around
logging.error to reduce the number of "implementations" of logging an error message; doing the thing itself instead is simpler and more maintainable.) Especially when it means that key logic that I need to read to understand what it's doing and investigate/fix bugs is now spread across multiple different files and classes rather than in a simple "X then Y then Z" procedural code block.

This decouples the queue handling, so that when debugging an issue or writing test cases, the queue can be largely ignored. They all pretty much were doing the same thing, but three different ways. I still think there is definitely room for simplifying further, but it works, has tests, and is relatively clean.

Added some replies to previous comments, then tried to figure out how the SpaceDockAdder works now, which led me down the rabbit hole of "when is game getting set," which was confusing because game might be a str or a Game depending on context. Added suggestions for those.

Yeah, valid critique. Have updated and the tests look good.

@techman83
Copy link
Member Author

@HebaruSan - any other blockers here? #288 + #289 are considerably more tightly scoped, so they should be much less to get across after this one.

@HebaruSan

This comment was marked as resolved.

@techman83
Copy link
Member Author

techman83 commented Apr 4, 2023

It's not really a code smell, rather a pattern that's an artifact of a "typed" runtime language. Personally I'd rather see it battle tested than spend too much time worrying about code smells. It has tests, we can refactor if we find a better way to achieve the same goal.

@HebaruSan

This comment was marked as resolved.

@techman83
Copy link
Member Author

At this point I'd rather not make any further changes to the PR. Ultimately it's a pretty common python pattern, and the decision to do it this way were unrelated to any thought towards performance.

@HebaruSan

This comment was marked as outdated.

@techman83
Copy link
Member Author

Ultimately it's a stylistic choice and I'm being stubborn. On reflection if that makes it easier and gets it across the line, I'm good with that.

Copy link
Member

@HebaruSan HebaruSan left a comment

Choose a reason for hiding this comment

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

Let's goooo! 🏃
(I'll leave this for you to merge, so you can monitor it during deployment and rebase other PRs as needed)

@techman83 techman83 merged commit 1b6e52e into KSP-CKAN:master Apr 6, 2023
@techman83 techman83 deleted the refactor/queue_handler branch April 6, 2023 06:54
@HebaruSan
Copy link
Member

HebaruSan commented Apr 7, 2023

It's not really a code smell

Here's an explanation of what "code smell" means:

It's doesn't refer (only) to a kind of warning from a linter. It's when "part of a program is not ideally structured, not necessarily an error or a bug". Examples given are:

  • long method
  • long parameter list
  • large class
  • lazy class
  • duplicated code
  • message chains

"Extra code" (5+ lines to do 1 line of work) and "unmotivated lazy initialization" are in the same category of concerns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement New feature or request Environment It's about the dev/prod environment In Progress Indexer Receives inflated modules and adds them to CKAN-meta Scheduler Adds netkans to the queue to be inflated Webhooks Listens for notifications and triggers actions via queues
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants