The FioriRecommendationHandler currently maintains a manually tenant-scoped negative cache using raw Caffeine:
private final Cache<String, Boolean> entitiesWithoutPredictionsPerTenant =
Caffeine.newBuilder().maximumSize(10_000).build();
Tenant-scoping is done via manual composite string keys (tenantId + ":" + entityName), and model-change invalidation requires a dedicated RecommendationModelChangedHandler that listens for MODEL_CHANGED events.
This should be replaced with the framework-provided TenantAwareCache<T, CdsModel> from cds-services-utils, which:
- Auto-resolves the tenant from
RequestContext (no manual key construction).
- Auto-invalidates when the CDS model changes via a
WeakReference<CdsModel> validator - when extensibility deploys a new model for a tenant, the cache entry is recomputed on next access. This eliminates the need for RecommendationModelChangedHandler entirely.
- Picks up standard cache configuration (
cds.model.provider.cache.maxSize, cds.model.provider.cache.expirationTime) from application properties, giving operators control without code changes.
- Follows the established pattern used throughout
cds-services (e.g., InactiveHandler, DraftGCHandler, AuthorizationDefaultOnHandler).
Suggested approach:
- Change the cache field to
TenantAwareCache<Set<String>, CdsModel> where the Set<String> holds entity qualified names that have no prediction columns for that tenant.
- Use
ConcurrentHashMap::newKeySet as the value supplier (thread-safe mutable set per tenant).
- Delete
RecommendationModelChangedHandler and its registration in RecommendationConfiguration.
The FioriRecommendationHandler currently maintains a manually tenant-scoped negative cache using raw Caffeine:
Tenant-scoping is done via manual composite string keys (
tenantId + ":" + entityName), and model-change invalidation requires a dedicatedRecommendationModelChangedHandlerthat listens forMODEL_CHANGEDevents.This should be replaced with the framework-provided
TenantAwareCache<T, CdsModel>fromcds-services-utils, which:RequestContext(no manual key construction).WeakReference<CdsModel>validator - when extensibility deploys a new model for a tenant, the cache entry is recomputed on next access. This eliminates the need forRecommendationModelChangedHandlerentirely.cds.model.provider.cache.maxSize,cds.model.provider.cache.expirationTime) from application properties, giving operators control without code changes.cds-services(e.g.,InactiveHandler,DraftGCHandler,AuthorizationDefaultOnHandler).Suggested approach:
TenantAwareCache<Set<String>, CdsModel>where theSet<String>holds entity qualified names that have no prediction columns for that tenant.ConcurrentHashMap::newKeySetas the value supplier (thread-safe mutable set per tenant).RecommendationModelChangedHandlerand its registration inRecommendationConfiguration.