[
https://issues.apache.org/jira/browse/UNOMI-1016?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Serge Huber updated UNOMI-1016:
-------------------------------
Fix Version/s: unomi-4.0.0
(was: unomi-4.1.0)
> Public API key lookup reads every tenant on each request
> --------------------------------------------------------
>
> Key: UNOMI-1016
> URL: https://issues.apache.org/jira/browse/UNOMI-1016
> Project: Apache Unomi
> Issue Type: Improvement
> Affects Versions: unomi-4.0.0
> Reporter: Serge Huber
> Priority: Major
> Fix For: unomi-4.0.0
>
>
> h3. Summary
> Every request to a public endpoint (context.json, eventcollector, client)
> looks up its tenant by API key with {{TenantServiceImpl.getTenantByApiKey}}.
> That method loads every tenant from the search engine
> ({{persistenceService.getAllItems(Tenant.class)}}, which is a scroll query
> over all tenant documents), deserializes them, and compares the key against
> each tenant's key hashes. The GraphQL endpoint does the same for public keys
> and for private keys.
> The cost grows with the number of tenants and is paid on every tracked page
> view and event. On a server where tenants are created at runtime, with
> hundreds or thousands of tenants, this becomes the dominant per-request cost,
> and it opens a scroll context in the search engine for each request.
> h3. Where
> * {{TenantServiceImpl.getTenantByApiKey(String, ApiKeyType)}}:
> {{executeAsSystem(() -> persistenceService.getAllItems(Tenant.class))}}, then
> a linear scan.
> * Callers: {{AuthenticationFilter}} (public paths),
> {{GraphQLServletSecurityValidator}} (public and private keys).
> * Key hashes are SHA-256 ({{SecretHashServiceImpl}}), so the comparison
> itself is cheap; the cost is the query and the deserialization.
> h3. Ways to explore
> * Keep an in-memory index from key hash to tenant id, rebuilt when tenants or
> keys change (the same snapshot approach UNOMI-1013 uses for tenant origins:
> loaded at start, updated on save, refreshed periodically and on a miss,
> rate-limited).
> * Or query by key hash: store the hash in an indexed field and look it up
> with a term query instead of loading every tenant. Revoked and expired keys
> must still be refused.
> * Either way: a key that was just generated or revoked must take effect
> promptly on all nodes; document the propagation delay.
> h3. How to test
> * A public request with a valid key does not load all tenants (unit test on
> the lookup, counting persistence calls).
> * A newly generated key works on the next request; a revoked or expired key
> is refused.
> * Measure request latency with, for example, 1,000 tenants before and after.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)