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

Remove external integrations from collection integrations (PP-503) #1494

Merged
merged 24 commits into from
Nov 17, 2023

Conversation

jonathangreen
Copy link
Member

@jonathangreen jonathangreen commented Nov 1, 2023

Description

This PR changes the data model for our collections in a number of ways with the goal of removing all reliance on external integrations from our collections.

All the database columns and tables "removed" by this PR have just been renamed on the Python side, but left in place for now. Once this goes into a release #1498 can be merged to remove the now unused tables and columns.

The major changes:

  • The external_integration_id column has been removed.
  • Collections no longer have a name column.
    • Previously both integrations and collections had names, this meant that they could get out of sync. Now collection names are driven by the name of their integration. A migration handles making sure that the existing integrations that have gotten out of sync are updated to have their collections name.
  • The collections_libraries table has been removed.
    • Collections used to be able to be related to libraries in two ways: through the collections_libraries table, and via their integration_library_configuration. This situation was confusing, and meant that these could get out of sync.
  • The collection table no longer uses its external_account_id column. This was duplicated between the table and the settings before, it now lives only in the settings. As with the others the column is still present, but is renamed and unused and will be dropped once this is rolled out everywhere.
  • The settings column get a gin index, to make it easier to query the jsonb column.
  • Some of the properties on the collection class have been moved out to the specific license provider API that used them. These were on the collection model because previously some providers didn't have their own API classes.
    • There are still some of these that could be moved into a more suitable location, but that can happen in a follow up PR.
  • The collection controller and collection self test controller have been updated to use the integration settings controller base classes. This lets us keep all the logic for updating these settings isolated there. The biggest consequence of this change is that we now pass around the integration ID rather then the collection ID when referencing collections and collection self tests.
    • This is transparent to the admin UI, since it just sends back the IDs given to it when it queries for the collection settings.
    • This makes the collection controllers act like the other controllers that modify integrations, rather then using different IDs in the collection controller.
  • The collection self test controller removes the special case that used to exist for OPDS importer collections, since they now have their own API class.
    • This PR removes the self test functionality for the OPDS 1.x importer class, since we don't have any OPDS 1.x collections in our production CMs. Here is a ticket to add self tests for the collection classes missing them (OPDS 2, OPDS 2 + ODL), but this is the situation we've been in for awhile, so no impact from this PR. This PR will make it easier to add these self tests by just implementing the self test interface in the api classes.
    • There is also a DB migration to apply these database changes and an associated migration test.
  • All the major files touched by this PR are now fully type hinted, and added to the strict mypy group in pyproject.toml.

Motivation and Context

Remove external integrations from collections PP-503.

How Has This Been Tested?

  • Light local testing with the CM admin UI:
    • Setting up collections
    • Running migrations
    • Associating and disassociating libraries
  • CI tests

Checklist

  • I have updated the documentation accordingly.
  • All new and existing tests passed.

Copy link

codecov bot commented Nov 1, 2023

Codecov Report

Attention: 15 lines in your changes are missing coverage. Please review.

Comparison is base (8cbe939) 90.40% compared to head (94efafa) 90.39%.

Files Patch % Lines
core/model/collection.py 84.61% 3 Missing and 3 partials ⚠️
api/admin/controller/collection_settings.py 93.42% 1 Missing and 4 partials ⚠️
core/opds2_import.py 40.00% 2 Missing and 1 partial ⚠️
core/integration/base.py 95.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1494      +/-   ##
==========================================
- Coverage   90.40%   90.39%   -0.01%     
==========================================
  Files         233      233              
  Lines       29371    29157     -214     
  Branches     6860     6799      -61     
==========================================
- Hits        26552    26357     -195     
+ Misses       1796     1783      -13     
+ Partials     1023     1017       -6     
Flag Coverage Δ
Api 73.83% <90.03%> (+0.04%) ⬆️
Core 61.06% <29.96%> (+0.09%) ⬆️
migration 29.42% <16.61%> (+0.12%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@jonathangreen jonathangreen force-pushed the feature/remove-external-integration-collection branch from c8f6854 to cadf562 Compare November 1, 2023 23:18
@jonathangreen jonathangreen changed the title Remove external integrations from collection integrations Remove external integrations from collection integrations (PP-503) Nov 2, 2023
@jonathangreen jonathangreen added the DB migration This PR contains a DB migration label Nov 2, 2023
@jonathangreen jonathangreen marked this pull request as ready for review November 2, 2023 23:09
@jonathangreen jonathangreen requested a review from a team November 2, 2023 23:10
api/admin/problem_details.py Show resolved Hide resolved
api/controller.py Show resolved Hide resolved
api/integration/registry/license_providers.py Show resolved Hide resolved
core/model/__init__.py Show resolved Hide resolved
core/model/integration.py Show resolved Hide resolved
core/model/integration.py Show resolved Hide resolved
core/model/listeners.py Show resolved Hide resolved
core/model/library.py Show resolved Hide resolved
@jonathangreen jonathangreen force-pushed the feature/remove-external-integration-collection branch from c9817fe to 2a439b9 Compare November 3, 2023 17:20
@jonathangreen jonathangreen force-pushed the feature/remove-external-integration-collection branch from 2a439b9 to eafb469 Compare November 3, 2023 17:35
Copy link
Contributor

@RishiDiwanTT RishiDiwanTT left a comment

Choose a reason for hiding this comment

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

This took a while 😅
I mostly had comments about the migration, most of the rest seemed A-OK 👌


log = logging.getLogger(f"palace.migration.{revision}")
log.setLevel(logging.INFO)
log.disabled = False
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe these 3 lines can be a util method like get_migration_logger(revision)

# value, then make it non-nullable.
op.add_column(
"integration_configurations",
sa.Column("context", postgresql.JSONB(astext_type=sa.Text()), nullable=True),
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not set nullable=False with default='{}' here rather than later?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think that you can use default with a new column in a table that has existing data.

When I try that the migration fails for me with:

E       sqlalchemy.exc.IntegrityError: (psycopg2.errors.NotNullViolation) column "context" contains null values
E
E       [SQL: ALTER TABLE integration_configurations ADD COLUMN context JSONB NOT NULL]

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah ok, yes default is an application level default. Using server_default will work, I tested it out.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think this changes the DB level schema though, right?

So migrated tables would have a different schema definition then tables that weren't migrated. We could mitigate this by changing the column definition to use server_default, but since none of our other tables with defaults use server_default, I'd rather leave it as default for consistency.

api/admin/controller/settings.py Show resolved Hide resolved
api/admin/controller/settings.py Show resolved Hide resolved
api/odl.py Outdated
@@ -78,7 +78,7 @@ class ODLAPIConstants:


class ODLSettings(OPDSImporterSettings):
external_account_id: Optional[HttpUrl] = FormField(
external_account_id: HttpUrl = FormField(
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that we are using pydantic for this attribute (and not ignoring it anymore in favour of the collection.external_account_id) this is causing problems for me locally since some of my feeds are http://localhost and HttpUrl has require_tld=True. This can go away with me changing my local settings, but it's something all the developers will need to be aware of.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm that's a good point... I maybe I'll change this one to AnyHttpUrl, so its a bit less strict.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated this one.

core/model/__init__.py Show resolved Hide resolved
@@ -37,7 +37,7 @@
from core.model.patron import Hold, Loan, Patron


class ODL2Settings(OPDS2ImporterSettings, ODLSettings):
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume the side effect of this making username and password mandatory was on purpose

Copy link
Member Author

Choose a reason for hiding this comment

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

It is intentional, I think these were changed to non-required by accident in #1189. If you checkout 299003e and take a look at the config, the configuration form in this PR matches what I see there.

@jonathangreen
Copy link
Member Author

@RishiDiwanTT I think I've got all the code review feedback resolved here. Pinging you for another review.

Copy link
Contributor

@RishiDiwanTT RishiDiwanTT left a comment

Choose a reason for hiding this comment

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

Looks good 👍

@jonathangreen jonathangreen merged commit f3b9c9b into main Nov 17, 2023
30 checks passed
@jonathangreen jonathangreen deleted the feature/remove-external-integration-collection branch November 17, 2023 13:58
jonathangreen added a commit that referenced this pull request Nov 29, 2023
Clean up leftover columns from #1494, now that it has gone into a release.
@jonathangreen jonathangreen restored the feature/remove-external-integration-collection branch February 6, 2024 16:18
@jonathangreen jonathangreen deleted the feature/remove-external-integration-collection branch February 6, 2024 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DB migration This PR contains a DB migration
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants