Sharing Levels cache¶
Sharing-level resolution is used by many queries, mutations, filters, and federated service calls. The cache design reduces repeated sharing-level database reads while keeping behavior correct across multiple service replicas.
Cache layers¶
Sharing Levels uses two cache layers with different responsibilities:
SharingLevelsDistributedCacheStorecaches raw store data in the distributed cache throughISuiteHybridCache. It disables the hybrid local-memory layer withUseLocalCache = false, so the store cache is shared across replicas without keeping another copy of the raw collections in every process.MemoizationSharingLevelsResolverusesIMemoryCachefor derived resolver calculations. This is per-process memoization for values such as parent chains, branches, lookup levels, destination levels, parent ids, and the list of sharing-level ids.
ASP.NET HybridCache can provide local-memory caching, but Sharing Levels does
not use that local layer in the store because the resolver already owns the
feature-specific memoization. This keeps the distributed raw-data cache and the
in-memory derived-result cache from duplicating the same responsibility.
Cached data¶
The store-level cache contains raw data loaded from the Sharing Levels database:
| Data | Source method | Empty collection behavior |
|---|---|---|
| Sharing levels | GetSharingLevels |
Not cached, because an empty result can mean the store is not ready yet. |
| Entity sharings | GetEntitySharings |
Not cached, because an empty result can mean the store is not ready yet. |
| Sharings | GetSharings |
Cached, because an empty sharings set can be a valid result. |
| Sharing-level ready marker | IsSharingLevelsReady |
Written after sharing levels are loaded with values. |
| Entity-sharing ready marker | IsEntitySharingsReady |
Written after entity sharings are loaded with values. |
The resolver-level memoization contains derived data only. It is cleared by moving to a new memoization generation, so old in-memory entries become unreachable without scanning and removing each individual key.
Invalidation¶
ISharingLevelsResolver.ClearAsync invalidates both layers:
- The resolver changes its memoization generation.
- Each
ISharingLevelsStoreCacheInvalidatorclears its store-level entries. SharingLevelsDistributedCacheStorewrites a short-lived distributed write-suspension marker.- The store removes raw collection keys and readiness markers from the distributed cache.
While the write-suspension marker exists, replicas still read from the database when needed, but they do not repopulate the distributed cache. This avoids a race where one replica clears the cache and another replica immediately writes old data back while invalidation is still settling.
Options¶
SharingLevelsStoreModuleOptions controls the store-level distributed cache:
| C# | |
|---|---|
DistributedCacheExpirationInSecondssets the store cache entry duration. The default is 600 seconds. A value of 0 or less omits the per-entry expiration override.DistributedCacheWriteSuspensionInSecondssets how long distributed cache writes are suspended after invalidation. The default is 5 seconds. A value of 0 or less disables write suspension.
SharingLevelsClientModuleOptions.MemorizationTimeInSeconds controls the
resolver IMemoryCache expiration for derived calculations.
Measuring impact¶
Use the Suite CLI manual performance command to compare the current branch with a baseline branch or commit:
| Bash | |
|---|---|
The report includes elapsed time, database command counters, cache counters, and memory measurements. See the Suite CLI documentation for report paths and command options.