Class RedisContextCache
Stores one canonical JSON representation per context (including the computed
Context.PATH field) together with structural index keys that enable
UUID→path and path→UUID lookups and tree reconstruction without a
local JVM cache.
All operations degrade gracefully: if Redis is unavailable every method
either returns null / an empty collection or falls through to the
supplied fallback, allowing callers to read directly from the database.
Key TTL: Equal to ContextCache.expiringTimeout (default 6 h).
The entire context key space is invalidated on every write via
invalidateAll() so stale data never persists longer than one TTL
period even if an explicit invalidation is missed.
Every complete snapshot also carries a format-qualified durable Context version from OrientDB. Reads reject a missing, differently formatted, or stale version, so incompatible data or data retained by Redis across an outage cannot become visible after the service format or database state changes.
- Author:
- Luca Frosini (ISTI - CNR)
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfaceProvider interface for warm up tasks. -
Method Summary
Modifier and TypeMethodDescriptionvoidaddNewContextToCache(UUID uuid, String name, UUID parentUuid) Adds a newly-created context to the Redis cache without a full invalidation.org.gcube.informationsystem.dag.Dag<org.gcube.informationsystem.contexts.reference.entities.Context>Builds aDag-backed tree of contexts from the data currently held in Redis (single-parent only --setAllowMultipleInheritance(false)-- since a context always has exactly one parent).List<org.gcube.informationsystem.contexts.reference.entities.Context>getAll()Returns the list of unmarshalled Context objects from Redis.Returns the raw JSON strings for all contexts in insertion order.static RedisContextCacheReturns the singleton instance ofRedisContextCache.getPathByUUID(String uuidStr) Convenience overload that parses the string representation of the UUID.getPathByUUID(UUID uuid) Returns the computed path string for the given context UUID (e.g.getRawByPath(String path) Returns the raw canonical JSON of the live context the given path resolves to: the one whose current path it is or, failing that, the one keeping it among its previous paths — a current path always wins.getRawByUUID(String uuidStr) Convenience overload that parses the string representation of the UUID.getRawByUUID(UUID uuid) Returns the raw canonical JSON string for the given context UUID as stored in Redis (includes the injectedpathfield).getUUIDByPath(String path) Returns the UUID of the context identified by the given path (e.g.getUUIDByPreviousPath(String path) Returns the UUID of the context that keeps the given path among its previous paths.voidinvalidate(UUID uuid) Performs a targeted invalidation of all Redis keys for the given context UUID.voidDeletes allctx:*keys from Redis using a SCAN loop.booleanReturnstruewhen Redis is reachable and the connection is open.booleanisEmpty()Returnstrueif the cache list is empty or unavailable.static voidRegisters a customRedisContextCache.CacheWarmUpProviderfor this cache.voidremoveChildFromParentJson(UUID parentUuid, UUID childUuid) Removes a deleted child context from the parent's cached JSONchildrenarray.voidPersists the complete list of contexts to Redis.voidsaveAll(List<org.gcube.informationsystem.contexts.reference.entities.Context> contexts, long contextVersion) Convenience overload for callers that only haveContextPOJOs at hand (e.g.voidsaveAll(org.gcube.com.fasterxml.jackson.databind.node.ArrayNode contexts, long contextVersion) Persists a complete Context snapshot given as raw JSON object nodes, and publishes its authoritative version last.voidupdateContextJson(UUID uuid, String contextJsonWithoutPath) Updates only the canonical JSON stored atctx:uuid:{uuid}, preserving the existingpaththat was injected at write time.
-
Method Details
-
registerWarmUpProvider
Registers a customRedisContextCache.CacheWarmUpProviderfor this cache.- Parameters:
provider- the custom provider to register
-
isEmpty
public boolean isEmpty()Returnstrueif the cache list is empty or unavailable.- Returns:
trueif the cache is empty or Redis is down,falseotherwise
-
getInstance
Returns the singleton instance ofRedisContextCache.- Returns:
- the singleton instance
-
isAvailable
public boolean isAvailable()Returnstruewhen Redis is reachable and the connection is open.- Returns:
trueif Redis cache is available,falseotherwise
-
saveAll
Persists the complete list of contexts to Redis. For each context this method:- Serialises the context to JSON via
ElementMapper. - Reads the already-available
Context.PATHfield from the JSON payload and validates it before writing index keys. - Writes all required index keys (
uuid,path,fname,parent,children, and the sharedlistZSET).
All keys are given a TTL equal to
ContextCache.expiringTimeout.If Redis is unavailable this method is a no-op.
- Parameters:
contexts- ordered list of contexts as returned byContextManagement.allFromDatabase()
- Serialises the context to JSON via
-
saveAll
public void saveAll(List<org.gcube.informationsystem.contexts.reference.entities.Context> contexts, long contextVersion) Convenience overload for callers that only haveContextPOJOs at hand (e.g. hand-built test fixtures). Marshals each one to JSON and delegates to the canonicalsaveAll(ArrayNode, long).Production code populating the cache from a real database read should prefer
saveAll(ArrayNode, long)directly with the already-serialized payload (seeContextRepository#warmUpCache()), rather than round-tripping through this POJO overload: unmarshalling intoContext/ContextImpland marshalling back widens theparent/childrensummaries to every model-level field (e.g.history), since the model'sgetParent()/getChildren()only guard against infinite recursion, not against re-exposing fields the original serializer deliberately omitted from those nested summaries.- Parameters:
contexts- the complete Context snapshotcontextVersion- the authoritative version represented by the snapshot
-
saveAll
public void saveAll(org.gcube.com.fasterxml.jackson.databind.node.ArrayNode contexts, long contextVersion) Persists a complete Context snapshot given as raw JSON object nodes, and publishes its authoritative version last. This is the canonical write path: each context's JSON node is stored exactly as its serializer produced it (e.g.ContextManagement's allow-listedparent/childrensummaries), with no JSON→POJO→JSON round trip that could reintroduce a field the summary deliberately omits.- Parameters:
contexts- the complete Context snapshot, one JSON object node per ContextcontextVersion- the authoritative version represented by the snapshot
-
getAllRaw
Returns the raw JSON strings for all contexts in insertion order. Each JSON string includes thepathfield injected at write time.- Returns:
- ordered list of raw JSON strings, or
nullif Redis is unavailable
-
getAll
public List<org.gcube.informationsystem.contexts.reference.entities.Context> getAll() throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryExceptionReturns the list of unmarshalled Context objects from Redis.- Returns:
- ordered list of Context objects, or
nullif Redis is unavailable - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- on deserialization errors
-
getRawByUUID
Returns the raw canonical JSON string for the given context UUID as stored in Redis (includes the injectedpathfield).- Parameters:
uuid- the UUID of the context to read- Returns:
- the raw JSON string, or
nullif not present or Redis is unavailable
-
getRawByUUID
Convenience overload that parses the string representation of the UUID.- Parameters:
uuidStr- the UUID string- Returns:
- the raw JSON string, or
nullif not present or Redis is unavailable
-
getPathByUUID
Returns the computed path string for the given context UUID (e.g./gcube/devsec/devVRE).- Parameters:
uuid- the UUID of the context- Returns:
- the path string, or
nullif not found or Redis is unavailable
-
getPathByUUID
Convenience overload that parses the string representation of the UUID.- Parameters:
uuidStr- the UUID string- Returns:
- the path string, or
nullif not found or Redis is unavailable
-
getUUIDByPath
Returns the UUID of the context identified by the given path (e.g./gcube/devsec/devVRE).- Parameters:
path- the fully-qualified context path- Returns:
- the resolved
UUID, ornullif not found or Redis is unavailable
-
getRawByPath
Returns the raw canonical JSON of the live context the given path resolves to: the one whose current path it is or, failing that, the one keeping it among its previous paths — a current path always wins. The cache is validated once for the whole lookup.- Parameters:
path- the path to resolve- Returns:
- the raw JSON string, or
nullif not found or the cache must not be trusted
-
getUUIDByPreviousPath
Returns the UUID of the context that keeps the given path among its previous paths. Callers look the current path up first (getUUIDByPath(String)): a current path always wins over a previous one.- Parameters:
path- the previous path- Returns:
- the resolved
UUID, ornullif not found or Redis is unavailable
-
buildContextsTree
public org.gcube.informationsystem.dag.Dag<org.gcube.informationsystem.contexts.reference.entities.Context> buildContextsTree() throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryExceptionBuilds aDag-backed tree of contexts from the data currently held in Redis (single-parent only --setAllowMultipleInheritance(false)-- since a context always has exactly one parent). Constructed on-demand each time this method is called; no JVM-level cache is maintained.- Returns:
- the contexts tree, or
nullif Redis is unavailable or empty - Throws:
org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException- on deserialization errors
-
updateContextJson
Updates only the canonical JSON stored atctx:uuid:{uuid}, preserving the existingpaththat was injected at write time.Use this for operations that change a context's content (e.g. state or metadata) but do NOT affect the tree structure or path of any context.
If the context's
pathis not found in Redis (e.g. after a restart before the first warm-up), falls back toinvalidateAll().- Parameters:
uuid- the UUID of the context whose JSON should be refreshedcontextJsonWithoutPath- serialized context JSON (withoutContext.PATHinjected)
-
invalidateAll
public void invalidateAll()Deletes allctx:*keys from Redis using a SCAN loop. Called after every context write (create / update / delete / changeState) to ensure subsequent reads reflect the latest DB state. -
invalidate
Performs a targeted invalidation of all Redis keys for the given context UUID. Also removes the context from its parent's children set and from the ZSET.- Parameters:
uuid- the UUID of the context to invalidate
-
addNewContextToCache
Adds a newly-created context to the Redis cache without a full invalidation.Writes all lookup keys for the new context (
ctx:path,ctx:fname,ctx:parent, membership inctx:childrenof its parent, and entry inctx:list). The parent's canonical JSON blob (ctx:uuid:{parentUuid}) is deleted so that the nextreadAsString(parentUuid)falls back to the database and reflects the new child.The new context's own JSON blob (
ctx:uuid:{uuid}) is intentionally not written here.getAllRaw()andgetAll()detect the missing blob and trigger a full cache reload on the firstall()call after the creation, so the response is always consistent.If the parent's path is not in the cache (cold cache), this method falls back to a full
invalidateAll()so the cache remains coherent.- Parameters:
uuid- UUID of the newly-created contextname- simple name of the new context (e.g."D4Science")parentUuid- UUID of its parent context, ornullfor a root context
-
removeChildFromParentJson
Removes a deleted child context from the parent's cached JSONchildrenarray. Call this afterinvalidate(UUID)when deleting a leaf context. The parent's JSON is updated in-place inside Redis; no database read is needed.- Parameters:
parentUuid- UUID of the parent context whose JSON must be patchedchildUuid- UUID of the child context that was just deleted
-