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

Extract report logic #323

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open

Extract report logic #323

wants to merge 18 commits into from

Conversation

Robin5605
Copy link
Contributor

Closes #298

Add a Storage protocol that abstracts our storage layer from the
business logic layer. This provides for a cleaner interface and more
ergonomic tests.
Tests are significantly faster when we aren't doing set up and teardown
database operations for every test, even ones that aren't database
tests.
Add a mock database class which abides by the Storage protocol. This
will allow us to mock out the database in some integration tests.
Add a fixture which yields a DatabaseStorage. This idea is to replace
the db_session fixture over time with this fixture.
This marker should be used on all tests that reach for a real database
to denote that they may be slow and require a database container to be
spun up before this test can be run. This will allow developers who are
not making any database changes to run their tests very quickly. All
tests (including database ones) should still be run in CI.
@Robin5605 Robin5605 requested review from a team as code owners October 6, 2024 01:03
@Robin5605
Copy link
Contributor Author

Checks should pass once #325 is merged

AbooMinister25
AbooMinister25 previously approved these changes Oct 6, 2024
Copy link
Contributor

@AbooMinister25 AbooMinister25 left a comment

Choose a reason for hiding this comment

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

LGTM

return self.sessionmaker()

def lookup_packages(
self, name: Optional[str] = None, version: Optional[str] = None, since: Optional[dt.datetime] = None
Copy link
Contributor

Choose a reason for hiding this comment

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

One suggestion to consider: expanding the parameters of this function to allow querying by package status or arbitrary filters. This would enable the function to be reused across different endpoints, not just the /report endpoint. More importantly, it would streamline things by reducing redundancy.
You could potentially absorb the functionality of get_reported_version, and possibly even validate_package.
As it stands;

  • get_reported_version serves as a helper function for parsing through a sequence of scans and verifying if they're reported - and raising an error if so. That could be absorbed by just directly querying (or better yet, filtering out) packages whose reported_at columns are null.

  • validate_package serves as a function for a validating if the given sequence of packages are within the given name and version parameters. This may be better placed as the access layer's responsibility (to ensure the right package whose given parameters are returned), or just outright absorbed into report_package.

What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

filename exceptions.py should be better i think


@cache
def get_storage() -> DatabaseStorage:
return DatabaseStorage(sessionmaker)
Copy link
Contributor

Choose a reason for hiding this comment

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

From the above comment, that means we should not cache here.


class DatabaseStorage(StorageProtocol):
def __init__(self, sessionmaker: orm.sessionmaker[Session]):
self.sessionmaker = sessionmaker
Copy link
Contributor

Choose a reason for hiding this comment

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

Each instance should have one session that commits changes when the DatabaseStorage gets destroyed. This is the 'Unit of Work" pattern.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I originally thought of using one DatabaseStorage instance across the whole program as a singleton, though we can also create and destroy them for each endpoint like you're suggesting. What are the advantages to this method, rather than having each individual method of this class manage it's own session and unit of work?

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.

Extract business logic from report.py endpoints
5 participants