Skip to content

Replace hand-rolled Caffeine cache with TenantAwareCache in FioriRecommendationHandler #78

Description

@Schmarvinius

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:

  1. Auto-resolves the tenant from RequestContext (no manual key construction).
  2. 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.
  3. Picks up standard cache configuration (cds.model.provider.cache.maxSize, cds.model.provider.cache.expirationTime) from application properties, giving operators control without code changes.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions