fix: order and bound the revisions query in WikiPage.get_context - #1
Open
Aanzan426 wants to merge 2 commits into
Open
fix: order and bound the revisions query in WikiPage.get_context#1Aanzan426 wants to merge 2 commits into
Aanzan426 wants to merge 2 commits into
Conversation
`get_context` loads every revision of a page, with full `content` on each, then uses only `revisions[0]` and `revisions[1]`. Correctness first: there is no `ORDER BY`, so `revisions[0]` is whatever the database happens to return first. It is not guaranteed to be the newest revision, which is what `context.current_revision` is used as. Today it is usually right by insertion order; that is luck, not a guarantee, and it can change with storage engine, replication or a table rebuild. Adding `order_by="creation desc"` makes it correct, and once the order is defined, `limit_page_length=2` makes it cheap. Measured on a page with 107 revisions: 32.7 ms to 5.7 ms, and 3.37 MB of revision content loaded to use 130 KB of it. The saving scales with edit history, so the pages that cost the most are the most-edited ones. No behaviour change for callers: the two values assigned are the same two, and the `len(revisions) > 1` branch still distinguishes a page with one revision.
Two tests in `test_wiki_page.py`: - `test_get_context_orders_revisions_by_creation_not_modified` gives three revisions a `modified` order opposite to their `creation` order, so the doctype's default `modified DESC` sort and chronological order disagree, then asserts `current_revision` and `previous_revision` are the two newest *by creation*. Verified to fail without the fix and pass with it. - `test_get_context_handles_a_page_with_one_revision` pins the single-revision case, where `previous_revision` must remain the "No Revisions" placeholder -- the branch most easily broken by adding a limit. Note for reviewers: my original description claimed the query had no `ORDER BY`. That was wrong. Frappe injects one from the doctype's `sort_field`, so the unpatched query emits `ORDER BY \`tabWiki Page Revision\`.\`modified\` DESC`. The ordering is therefore deterministic today, just sorted by the wrong column -- `modified` is when a row was last written, not when the revision was made, so touching an old revision presents it as the current one. The missing `LIMIT` is unaffected by that correction and remains the larger practical win.
Code Review - PR #1Reviewer: OpenClaw Bot SummaryThis is a small, targeted fix to What's Done Well
IssuesNo blocking issues found. File-by-File Summary
Note: GitHub reports no checks on this branch, so I reviewed the code and test intent but did not see CI results here.
|
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.
Bounds and orders the revisions query in
WikiPage.get_context. This is the Unity-owned copy of the change — mergeable by us, on the branch we actually deploy (master,2372f859f6).The problem
get_contextloads every revision of a page, with the fullcontentblob on each, then uses onlyrevisions[0]andrevisions[1]:Two problems, one large and one small.
1. There is no
LIMIT. Only two rows are ever used. On a page with 107 revisions that is 3.37 MB read to use 130 KB, and it grows with edit history — so the most-edited pages, usually also the most-read, pay the most.2. The ordering is by the wrong column. There is an implicit
ORDER BY— Frappe supplies one from the doctype'ssort_field, so the query emits:modifiedis when the row was last written, not when the revision was made. They coincide while revisions are only appended, but any write touching an older revision's row moves it to the front, and it is then handed to the template ascurrent_revision.The fix
Impact
Measured on a page with 107 revisions:
On a single-revision page the difference is negligible either way — this is not a median-case win, it is an outlier and correctness win.
Tests
test_get_context_orders_revisions_by_creation_not_modified— gives three revisions amodifiedorder deliberately opposite to theircreationorder, so the default sort and chronological order disagree, then assertscurrent_revision/previous_revisionare the two newest by creation. Verified to fail onmasterand pass with this change.test_get_context_handles_a_page_with_one_revision— pins the single-revision case, whereprevious_revisionmust stay the"No Revisions"placeholder. That is the branch aLIMITis most likely to break.Full
test_wiki_page.pysuite: 4 tests, all passing.Compatibility
No behaviour change for callers. The same two values are assigned, and
len(revisions) > 1still distinguishes a one-revision page: the query returns one row, so the placeholder path is preserved.Deployment note
Merging this puts the fix in the Unity fork. It only reaches walnut if the bench is pointed at the fork for
wiki— a separate decision, and one that cuts against the overrides-first approach used forwalnut_customizations#114. Merging here is still worth it: it means the fix exists somewhere we control rather than only in an upstream PR that may sit indefinitely.Ref: WalnutAppSuite/walnut_customizations#114