-
Notifications
You must be signed in to change notification settings - Fork 9
Make the non-BISAC nonfiction reset re-runnable (PP-5129) #3736
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
Changes from all commits
d02999e
61ae9b6
1f3cab4
5769c9a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| #!/usr/bin/env python | ||
| """Queue the reset_non_bisac_nonfiction_subjects Celery task. | ||
|
|
||
| Convenience wrapper that manually dispatches the repair for BISAC subjects | ||
| stored as nonfiction in error (the `reset_non_bisac_nonfiction_subjects` Celery | ||
| task) for a worker to process. | ||
| """ | ||
|
|
||
| from palace.manager.scripts.work import ResetNonBisacNonfictionSubjectsScript | ||
|
|
||
| ResetNonBisacNonfictionSubjectsScript().run() |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,6 +11,7 @@ | |||||||||||||||||||||||
| from palace.manager.celery.tasks.work import ( | ||||||||||||||||||||||||
| classify_unchecked_subjects, | ||||||||||||||||||||||||
| reclassify_null_audience_works, | ||||||||||||||||||||||||
| reset_non_bisac_nonfiction_subjects, | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
| from palace.manager.data_layer.policy.presentation import ( | ||||||||||||||||||||||||
| PresentationCalculationPolicy, | ||||||||||||||||||||||||
|
|
@@ -252,6 +253,25 @@ class WorkOPDSScript(WorkPresentationScript): | |||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| class ResetNonBisacNonfictionSubjectsScript(Script): | ||||||||||||||||||||||||
| """Manually dispatch the ``reset_non_bisac_nonfiction_subjects`` Celery task. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| The work itself happens in the Celery task; this script just queues it. It | ||||||||||||||||||||||||
| exists so the repair can be applied again on demand, in case its reset was | ||||||||||||||||||||||||
| consumed by old code before the new classifier was live everywhere. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| TODO: Remove this script when the ``reset_non_bisac_nonfiction_subjects`` | ||||||||||||||||||||||||
| Celery task is removed. | ||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def do_run(self, *args: Any, **kwargs: Any) -> None: | ||||||||||||||||||||||||
|
Comment on lines
+256
to
+267
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This adds Context Used: CLAUDE.md (source) Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
||||||||||||||||||||||||
| reset_non_bisac_nonfiction_subjects.delay() | ||||||||||||||||||||||||
| self.log.info( | ||||||||||||||||||||||||
| 'The "reset_non_bisac_nonfiction_subjects" task has been queued for ' | ||||||||||||||||||||||||
| "execution. See the celery logs for details about task execution." | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
|
Comment on lines
+268
to
+272
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The command discards the
Suggested change
Knowledge Base Used: |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| class ReclassifyNullAudienceWorksScript(Script): | ||||||||||||||||||||||||
| """Manually dispatch the ``reclassify_null_audience_works`` Celery task. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,54 @@ | ||||||||||||||||||||||||
| """Repair BISAC subjects stored as nonfiction because their code did not resolve. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Everything on the Palace Marketplace / Feedbooks category scheme is stored with | ||||||||||||||||||||||||
| ``type='BISAC'``, including codes that are not BISAC at all -- language and | ||||||||||||||||||||||||
| territory categories such as ``INFEN000`` ("English literature"). Those cannot | ||||||||||||||||||||||||
| be resolved to a canonical heading, so classification used to infer nonfiction | ||||||||||||||||||||||||
| from the distributor's name and store ``fiction=False``. The classifier no | ||||||||||||||||||||||||
| longer does that, which leaves the stored values stale. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Subjects are only re-examined when ``checked`` is false, so this dispatches two | ||||||||||||||||||||||||
| steps: ``reset_non_bisac_nonfiction_subjects`` marks the stale ones unchecked, | ||||||||||||||||||||||||
| then ``classify_unchecked_subjects`` re-scores them and recalculates their | ||||||||||||||||||||||||
| works. The second signature is immutable so the chain does not pass the first | ||||||||||||||||||||||||
| task's return value into it. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Doing both here matters. The reset on its own is exposed: anything reaching | ||||||||||||||||||||||||
| ``Subject.assign_to_genre`` before the re-score consumes it, and code running | ||||||||||||||||||||||||
| the superseded rules re-stamps ``checked=True`` with the same wrong value. | ||||||||||||||||||||||||
| Nothing errors and nothing revisits the subject afterwards, so the repair | ||||||||||||||||||||||||
| silently did nothing, having paid for a reindex to do it. Chaining the re-score | ||||||||||||||||||||||||
| closes that gap to seconds rather than waiting for the nightly run. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| The timing works out. ``helpers/migrate.yml`` stops the scripts container -- | ||||||||||||||||||||||||
| where every Celery worker and beat run -- before migrating, and starts it again | ||||||||||||||||||||||||
| from the new image afterwards, so the worker that picks this up is necessarily | ||||||||||||||||||||||||
| new code. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Web containers are the remaining exposure: the deploy recycles them after the | ||||||||||||||||||||||||
| migration step, and they can reach ``assign_to_genre`` through a presentation | ||||||||||||||||||||||||
| recalculation. Fargate deployments are not governed by that playbook at all. A | ||||||||||||||||||||||||
| second startup task re-applies the reset a release later, once no old code is | ||||||||||||||||||||||||
| running anywhere. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| TODO: Remove this task once it has run on all deployments (PP-5129).""" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| from __future__ import annotations | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| import logging | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| from celery.canvas import Signature, chain | ||||||||||||||||||||||||
| from sqlalchemy.orm import Session | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| from palace.manager.celery.tasks.work import ( | ||||||||||||||||||||||||
| classify_unchecked_subjects, | ||||||||||||||||||||||||
| reset_non_bisac_nonfiction_subjects, | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
| from palace.manager.service.container import Services | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def run(services: Services, session: Session, log: logging.Logger) -> Signature | None: | ||||||||||||||||||||||||
| return chain( | ||||||||||||||||||||||||
|
Comment on lines
+50
to
+51
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The new public
Suggested change
Context Used: CLAUDE.md (source) Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
||||||||||||||||||||||||
| reset_non_bisac_nonfiction_subjects.s(), | ||||||||||||||||||||||||
| classify_unchecked_subjects.si(), | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
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.
This adds the public
BISACClassifier.contradicts_stored_fictionhelper undersrc/palace/manager/core, but the repository explicitly markscoreas deprecated and prohibits new code there. Move the shared stale-classification logic to a supported package and have the classifier, migration, and task call it there. This repository requirement must be satisfied before merging.Context Used: CLAUDE.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!