TemplateService: ReconcileDescendantsAsync still loads the whole tracked template graph on member add/update #86
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
After #66, member add/update loads only the analysis closure for collision/lock checks, but
TemplateService.ReconcileDescendantsAsyncstill callsGetAllTemplatesAsync(tracked, with script bodies) on every add/update to propagate to derived templates. That is now the dominant cost of these paths on a large library. Load only the edited template's derived descendants plus what they resolve against (reuse the #66 closure walk in the descendant direction), with an equivalence test like #66's.Fixed on main
c29b99c6: ReconcileDescendantsAsync loads only the edited template's derived subtree + its parent chain (new TemplateReconcileClosure — the #66 walk run downward; repoGetTemplateReconcileClosureAsync, same tracked fully-loaded shape as GetAllTemplatesAsync). Compositions not needed (reconcile follows inheritance only). A leaf template costs one empty query and loads nothing. Equivalence: TemplateReconcileClosureTests (deep subtree, ancestor, composed module, look-alike trees, parent cycle, dangling parent) — identical adds/updates/deletes/audit rows/saves and resolver output for every template; 17 tests fail on the old service, 24 with the ancestor walk removed. Load: 5 templates / 10 attributes vs 47 / 94 (recorded SQL on SQLite). Trade-off: subtree case = 4 loads + 1 empty query instead of one whole-graph load, each bounded by the subtree. Evidence: TemplateEngine 574/574, ConfigurationDatabase 326 (133 skipped), ManagementService 721/721; re-run green after rebasing onto #79/#71/#69; slnx 0 warnings.