Skip to content

MID-11179 Improve user list performance for large orgRelation authorization#633

Open
kay1313 wants to merge 1 commit intomasterfrom
fix/MID-11179
Open

MID-11179 Improve user list performance for large orgRelation authorization#633
kay1313 wants to merge 1 commit intomasterfrom
fix/MID-11179

Conversation

@kay1313
Copy link
Copy Markdown
Contributor

@kay1313 kay1313 commented May 4, 2026

Summary

Improves performance of user list/search/count operations when authorization contains large orgRelation / managed-org filters.

The main problem was that users managing many organizations could produce very large OR predicates and repeated org descendant checks. This PR reduces that overhead in three places:

  1. Optimizes sqale OR query generation for compatible subtree OrgFilter branches.
  2. Batches post-filter orgRelation descendant checks.
  3. Avoids duplicate GUI countObjects calls during repeated Wicket size/page-count requests.

Changes

Sqale org OR optimization

Adds an optimizer for OR filters containing multiple compatible subtree org filters.

Instead of emitting many similar org EXISTS branches, compatible branches are grouped and emitted as a single predicate using ancestorOid.in(...).

The optimizer preserves fallback behavior for unsupported or mixed branches:

  • singleton org groups are handled by normal OR processing
  • unrelated OID branches are preserved
  • unsupported InOidFilter shapes are preserved
  • unrelated non-org filters remain in the OR
  • null/ANY relation and explicit relations are kept separate

Batched orgRelation post-filter checks

Adds OrgTreeEvaluator.isDescendantOfAny(...) and sqale repository support for checking multiple ancestor org OIDs in one closure query.

OrgRelationClause now uses the batched method for ALL_DESCENDANTS, while preserving existing semantics:

  • subjectRelation filters only the principal/subject parent org refs
  • target-side parent org relation remains unconstrained
  • includeReferenceOrg self-match is checked before descendant lookup
  • non-ALL_DESCENDANTS scopes continue using the existing path

GUI count cache

Adds a short-lived count cache in SelectableBeanDataProvider.

This avoids repeated countObjects calls when Wicket asks for provider size/page count multiple times during the same render cycle. The cache key includes:

  • object type
  • query
  • count options

The cache is cleared on provider detach and relevant state changes, and is independent of row/object caching.

Also updates concrete count implementations to use the query passed from internalSize(), so the counted query matches the cache key.


Tests

Added/updated tests for:

  • optimized org OR query semantics in sqale search
  • ANY/null vs explicit target parent relation behavior
  • self/OID branches from include-reference-org style filters
  • mixed relation groups and leftover OR branches
  • duplicate-safe search/count behavior
  • batched repository isDescendantOfAny(...)
  • selector-level OrgRelationClause batching semantics
  • GUI count cache reuse and invalidation

Validation

  • Added regression coverage for:
    • sqale optimized org-OR query semantics
    • selector-level orgRelation batching
    • repository-level isDescendantOfAny(...)
    • GUI provider count-cache reuse and invalidation
  • Manual profiling confirmed repeated page-count requests now hit the provider count cache within the same render.
  • Manual profiling on the reproduced large managed-org scenario showed the affected user list count/search path dropping from several seconds to sub-second execution, with remaining samples mostly in normal Wicket rendering/security/schema processing rather than repeated org-filter query construction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant