Skip to content

[#12486] fix(core): version-validate user/group entity cache via updated_at - #12487

Open
lasdf1234 wants to merge 6 commits into
apache:mainfrom
lasdf1234:fix/12486-user-group-cache-write-through
Open

[#12486] fix(core): version-validate user/group entity cache via updated_at#12487
lasdf1234 wants to merge 6 commits into
apache:mainfrom
lasdf1234:fix/12486-user-group-cache-write-through

Conversation

@lasdf1234

@lasdf1234 lasdf1234 commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

What changes were proposed in this pull request?

  • Add USER/GROUP to the entity-cache allowlist so name-keyed store.get can use the per-node cache.
  • Carry user_meta.updated_at / group_meta.updated_at on UserEntity / GroupEntity (and the corresponding POs/SQL selects).
  • On name-keyed get / exists / batchGet, version-validate cached USER/GROUP entries against *_meta.updated_at; invalidate and reload when the sentinel or id no longer matches (covers HA peers and updateById paths that do not emit entity change-log rows).
  • On RelationalEntityStore.update for USER/GROUP, invalidate the name key instead of cache.put, so the next read reloads a fresh snapshot with the new sentinel.
  • Remove unused User/Group mutation-by-externalId APIs that have no REST, Java client, or SCIM callers; keep getUserByExternalId / getGroupByExternalId and historical OperationType.REMOVE_*_BY_EXTERNAL_ID for audit log parsing.

Why are the changes needed?

After alterUserById / alterGroupById (for example SCIM PATCH active=false), name-based getUser / getGroup can keep serving a stale cached entity on peer nodes until TTL. GET-by-id is unaffected because it always hits the backend. Change-log invalidation alone is insufficient for USER/GROUP because updateById does not write entity_change_log.

Fix: #12486

Does this PR introduce any user-facing change?

Yes. These dispatcher/storage methods are removed:

  • removeUserByExternalId
  • removeGroupByExternalId
  • SupportsExternalIdOperations.updateByExternalId / deleteByExternalId (and the corresponding JDBC/UserMetaService paths)

No change to public REST APIs. Caching USER/GROUP is an internal store behavior; clients still see the same getUser / getGroup results, now without cross-node stale enabled / role snapshots.

How was this patch tested?

  • Unit: TestUserGroupEntityCacheVersionCheck (reload after updated_at advances; reload after delete)
  • Unit: TestBaseEntityCache (USER/GROUP are cacheable; ROLE remains non-cacheable)
  • Existing access-control / event / JDBC backend tests updated for the removed externalId mutation APIs

lasdf1234 and others added 3 commits August 18, 2026 18:34
…sed externalId mutations

update/updateById now put the updated entity into the name-keyed cache so later get-by-name sees the change. Remove unused remove/update/delete-by-externalId APIs; keep get-by-externalId.

Co-authored-by: Cursor <cursoragent@cursor.com>
…eThroughCache

The helper only wrapped cache.put; updateById never hits a rename.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ty_change_log

Name-keyed Caffeine cannot be updated on peers by cache.put. Write ALTER/DROP
rows for user/group so EntityCacheChangeLogListener can invalidate them, and
skip USER/GROUP in JCasbin so those rows do not warn.

Co-authored-by: Cursor <cursoragent@cursor.com>
@lasdf1234
lasdf1234 requested review from roryqi and yuqi1129 and removed request for yuqi1129 August 18, 2026 12:16
@lasdf1234 lasdf1234 self-assigned this Aug 18, 2026
roryqi
roryqi previously approved these changes Aug 18, 2026

@roryqi roryqi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

…a updated_at

Name-keyed get now reloads USER/GROUP when user_meta/group_meta.updated_at
has advanced, so HA peers do not serve a stale enabled flag or role list.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ith project conventions

Move the helper under storage.relational.utils, keep private methods at the
end of RelationalEntityStore, order builders with fields, and drop core
Javadoc references to the JCasbin authorizer.

Co-authored-by: Cursor <cursoragent@cursor.com>
@lasdf1234 lasdf1234 changed the title [#12486] fix(core): write-through user/group cache and drop unused externalId mutations [#12486] fix(core): version-validate user/group entity cache via updated_at Aug 19, 2026
Drop getFreshFromCache / isFresh / UserGroupEntityVersions. Name-keyed
USER/GROUP get uses the same getUserUpdatedAt / getGroupUpdatedAt probe
and id + updated_at comparison as loadUserRoles / loadGroupRoles.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

[Bug report] User/Group updateById leaves stale name cache; unused externalId mutation APIs

2 participants