Skip to content

Performance: encode tn_order from each node's stable key instead of a dense rank - #233

Draft
stumpylog wants to merge 2 commits into
fabiocaccamo:mainfrom
stumpylog:fix/tn-order-tree-local-path
Draft

Performance: encode tn_order from each node's stable key instead of a dense rank#233
stumpylog wants to merge 2 commits into
fabiocaccamo:mainfrom
stumpylog:fix/tn-order-tree-local-path

Conversation

@stumpylog

@stumpylog stumpylog commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Describe your changes

tn_order was a global dense-rank integer, so any insert/reorder/delete anywhere in the table could rewrite tn_order on every row of every tree.

It's now built from each node's own stable order key (priority + slug + pk), chained with its ancestors'. A node's segment never depends on its siblings, so no write anywhere else in the table can change it, including inserting a new root.

Measured on 50 trees x 40 nodes each, real save/signal/update_tree() path:

Before After
Insert deep in a tree: time / queries / rows changed elsewhere 4758ms / 11 / 1960 786ms / 7 / 0
Insert a new root: time / queries / rows changed elsewhere 2684ms / 11 / 2000 760ms / 7 / 0

Trade-offs

  • Breaking: get_order()/.order return an opaque sortable string, not a dense-rank integer.

Related issue
#45 (specifically this comment suggesting this exact approach), #34 (segments here are fixed-width per-node keys, not free text)

Checklist before requesting a review

  • I have performed a self-review of my code.
  • I have added tests for the proposed changes.
  • I have run the tests and there are not errors.

…lay-field models

- Fix string.letters (Python 2 only) to string.ascii_letters in CategoryWithStringPk
- Add TransactionTestCase to ModelWithStringPkTestCase, ModelWithUUIDPkTestCase, and ModelWithoutDisplayFieldTestCase so they are collected by the test runner
- Add treenode_display_field to CategoryWithoutDisplayField to enable display-related tests to pass on all four model tiers

Override test_get_display and test_get_tree_display in ModelWithoutDisplayFieldTestCase
to assert the pk-fallback behavior (get_display_text() returns str(pk)) rather than the
name-based display that the other three tiers expect.

This enables the test suite to run against all four concrete models (int pk, string pk, UUID pk, no-display-field) instead of just the int-pk tier. The test count increases from 85 to 232.
@stumpylog
stumpylog marked this pull request as draft August 26, 2026 20:02
@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.76%. Comparing base (3d9c571) to head (67b1f5f).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #233      +/-   ##
==========================================
+ Coverage   95.07%   95.76%   +0.69%     
==========================================
  Files          11       11              
  Lines         711      709       -2     
==========================================
+ Hits          676      679       +3     
+ Misses         35       30       -5     
Flag Coverage Δ
unittests 95.76% <100.00%> (+0.69%) ⬆️

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

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…lobal dense rank

tn_order was a global dense-rank integer, reassigned by sorting the
entire table on every write. Inserting or reordering one node could
force a tn_order rewrite on every row of every tree, not just the one
that changed.

It's now built from each node's own stable order key (priority + slug
+ pk, the same key already used to sort nodes for tree traversal),
chained with its ancestors'. A node's own segment never depends on its
siblings, so adding, removing, or reordering any node, including a new
root, never changes another node's tn_order.

tn_index/siblings/children still compute exactly as before, so
roots-as-siblings semantics are unchanged.
@stumpylog
stumpylog force-pushed the fix/tn-order-tree-local-path branch from 0b64b57 to 67b1f5f Compare August 27, 2026 14:46
@stumpylog stumpylog changed the title Performance: Update tn_order to a tree-local materialized path Performance: encode tn_order from each node's stable key instead of a dense rank Aug 27, 2026
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.

1 participant