Speed up the creation of worksheets with a worksheet template - #3004
Open
xispa wants to merge 5 commits into
Open
Speed up the creation of worksheets with a worksheet template#3004xispa wants to merge 5 commits into
xispa wants to merge 5 commits into
Conversation
The `idxs_cols` parameter conflated two different things, and its name suggested that naming a metadata column was enough to have it recomputed, while the opposite reading (that any match recomputes the whole record, like `reindexObject` does) was just as plausible. The signature follows now the convention of the catalogs: `idxs` for the indexes to reindex, `cols` for the metadata columns to recompute. Both accept None to mean "all of them", and `cols` accepts an empty list to not touch the metadata at all. The doctest covers the three cases.
`add_reference_analysis` and `add_duplicate_analysis` ended with `self.reindexObject(idxs=["getAnalysesUIDs"])`, that recomputes all the metadata of the worksheet, on every control, blank and duplicate created. Since part of that metadata is resolved by walking through all the analyses assigned, adding the QC analyses of a worksheet template was quadratic, same as adding the routine ones was. Both accept a `reindex` parameter now, and so do `addReferenceAnalyses` and `addDuplicateAnalyses`, that reindex the worksheet once when all the analyses are added. The application of a worksheet template skips it, cause it already reindexes the worksheet at the end. The defaults preserve the current behavior for the rest of callers. Neither of them resolves `getAnalyses()` anymore either, cause it wakes up all the analyses assigned on every QC analysis created. UIDs are enough. The doctest asserts the metadata of the worksheet record after applying a template and after adding analyses, duplicates and reference analyses in bulk, which was not covered before.
xispa
marked this pull request as ready for review
July 31, 2026 14:04
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description of the issue/feature this PR addresses
Creating a worksheet from a worksheet template takes an unreasonable amount of time on big instances, specially with templates with a high number of slots. Four things are responsible for that.
1. Every unassigned analysis of the system is woken up. The search for candidates in
applyWorksheetTemplateis unbounded, and the object is resolved before checking whether there is a slot left for its sample:With a backlog of a few thousand unassigned analyses matching the services of the template, thousands of objects are loaded from the database to fill a few dozen slots.
2. The worksheet is fully reindexed once per analysis added. Part of the metadata of a worksheet is resolved by walking through all the analyses assigned (
getNumberOfQCAnalyses,getNumberOfRegularAnalyses,getNumberOfRegularSamples) andgetProgressPercentageruns a catalog search. Reindexing on eachaddAnalysismakes the whole operation quadratic.3. The sample is fully reindexed twice per analysis added, once by the
after_assignevent of the analysis and once explicitly byaddAnalysis. A full reindex of a sample recomputes every index and metadata column, including the searchable text index and the columns resolved by walking through all its analyses, whileassigned_stateis the only value that actually changes.4. The QC analyses recompute the worksheet metadata one by one. Both
add_reference_analysisandadd_duplicate_analysisend withself.reindexObject(idxs=["getAnalysesUIDs"]). That call restricts the indexes, butupdate_metadatadefaults to 1 all the way down toProducts.ZCatalog, so every metadata column of the worksheet is recomputed on every single control, blank and duplicate created. Same quadratic pattern as (2) on a different path, and templates with 64 positions reserve a good share of them for QC.Current behavior before PR
Measured on a test instance (tiny catalogs, everything in the ZODB cache, so the reindexing costs here are a fraction of what they are in production). The first scenario assigns 40 analyses, the second one 10:
For the QC analyses, the full recomputes of the worksheet metadata grow with the number of controls, blanks and duplicates created: 6 of them for a slot with 3 duplicates.
Desired behavior after PR is merged
addAnalysisaccepts areindexparameter for that, andaddAnalysesrelies on it too, so adding a collection of analyses without a template benefits as welladdReferenceAnalyses,add_reference_analysis,addDuplicateAnalysesandadd_duplicate_analysisaccept areindexparameter as well. The plural ones reindex the worksheet once, when all the analyses are added, and the template application skips it, cause it reindexes the worksheet at the end anyway. The defaults preserve the current behavior, so the views that add blanks, controls and duplicates, as well as the retract event of a reference analysis (that callsadd_reference_analysisdirectly), need no changesafter_assignrestricts the reindex of the sample (and of its ancestors) toassigned_state. Theidxsparameter ofreindex_requestwas silently ignored, it is honored nowgetAnalysesis no longer used to keep track of the analyses assigned, neither inaddAnalysisnor when adding QC analyses, cause it wakes up all of them on every call. UIDs are enoughThis PR also adds a new function to the API,
api.reindex, used by the changes above:Only the indexes named in
idxsare reindexed (all of them when None), and catalogs without any of them are skipped.colsdoes the same for the metadata: all the columns are recomputed when None, only the named ones otherwise, and none at all when empty. Note this is not whatobj.reindexObject(idxs=[...])does, that restricts the indexes but recomputes all the metadata columns. Theuid_catalogis taken into account too, resolving its record with the path convention of the content type (relative to the portal root for AT contents, absolute for DX ones), so no duplicate record is left behind. The function is covered inAPI.rst.The
WorksheetApplyTemplatedoctest asserts now the metadata of the worksheet record after applying a template, and after adding analyses, duplicates and reference analyses in bulk, which was not covered before.Three notes for reviewers:
samples_slots[sample_uid]instead of the sortedsample_id), could assign the slot of one sample to a different one, ending up with two samples sharing a slot. It has been removed: slots keep the order in which the analyses are resolved, by priorityreindexOnModifysubscriber still reindexes it fully on every duplicate created. Traced with 3 duplicates, the full recomputes of the worksheet metadata go from 6 (one explicit and one implicit per duplicate) down to 4 (one implicit per duplicate plus the single explicit one at the end), so this path is improved, but not linear yet. Batching that event-driven reindex is out of the scope of this PR--
I confirm I have tested this PR thoroughly and coded it according to PEP8 and Plone's Python styleguide standards.