Skip to content

UNOMI-1002: Stop serializing public requests in compatibility mode - #915

Merged
sergehuber merged 3 commits into
masterfrom
UNOMI-1002-compat-tenant-cache
Oct 13, 2026
Merged

sergehuber merged 3 commits into
masterfrom
UNOMI-1002-compat-tenant-cache

Conversation

@sergehuber

@sergehuber sergehuber commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • TenantServiceImpl.getOrCreateTenant caches the tenant so single-tenant compatibility mode public requests (context.json, event collector) no longer wait on each other or hit persistence every time (UNOMI-1002 / follow-up to UNOMI-980).
  • The cache is local to each node and entries expire after about 30 seconds, so a tenant deleted or changed on another node, or directly in the search engine, is noticed without any node-to-node messaging. If the default tenant is gone, it is created again at that point.
  • While one thread reloads an expired entry, other requests keep using it rather than queue behind the read. Requests only wait when there is no entry at all (first request, or just after a local change).
  • On a single node, concurrent first requests go through one lock and create the tenant once. Two nodes creating it at the same instant are not coordinated, as before.
  • Entries are dropped on saveTenant, deleteTenant, and API-key generation, so local changes normally show on the next call. A load that overlaps the change can keep the earlier version until the entry expires.
  • Compatibility mode still uses the fixed tenant id default only (no request header can steer it). Multi-tenant paths do not use this cache.

https://issues.apache.org/jira/browse/UNOMI-1002

Test plan

  • mvn -pl services,rest test -Dtest=TenantServiceImplTest,AuthenticationFilterBlankPasswordTest
  • Each new cache test checked by breaking the code it guards (invalidation on delete and on API-key generation, expiry, non-blocking reload, lock, lock release)
  • CI unit tests
  • CI integration tests (Elasticsearch / OpenSearch) — existing SingleTenantCompatibilityModeIT (UNOMI-980) still passes

🤖 Generated with Claude Code

sergehuber and others added 3 commits October 10, 2026 07:20
Public requests no longer serialize on a method lock or re-read the
default tenant from persistence on every hit. Cache on first success,
lock only on miss, and invalidate on save/delete/key rotation.
The getOrCreateTenant cache was local to one node and never expired, so a
tenant deleted or changed on another node, or directly in the search
engine, was never noticed and the default tenant was not created again.

- Entries expire after 30 seconds. While one thread refreshes an expired
  entry the others keep answering from it rather than queue behind the read.
- A null tenant id is rejected with IllegalArgumentException again.
- Tests now fail when an invalidation, the expiry or the lock is removed,
  and cover API key generation, a delete on another node, a tenant created
  by another node during creation, and failures not being cached.
- Drop a catch that could never fire from the filter test.
- Document the cached, shared result on TenantService and in the manual.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The 30 seconds is not a hard bound: an expired entry is still served
  while a reload runs. Say so in the Javadoc and the manual.
- Retry from another thread in the failure test, so a lock left held by
  the failed call is detected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sergehuber
sergehuber merged commit 39d6c64 into master Oct 13, 2026
7 checks passed
@sergehuber
sergehuber deleted the UNOMI-1002-compat-tenant-cache branch October 13, 2026 05:42
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