Skip to content

v1.1.0 - Cache Layer Overhaul

Choose a tag to compare

@mustafabinguldev mustafabinguldev released this 25 Apr 17:27

v1.1.0 — Cache Layer Overhaul

Overview

This release is a full architectural redesign of the data synchronization layer (RedisDataContainer). The previous implementation had an ambiguous cache hierarchy, race conditions, and potential data loss paths. All known issues have been addressed.


What's New

Redis-Master Cache Hierarchy
Redis is now the single source of truth across all layers. No external process can override Redis data. Priority order is strictly enforced: Redis → L1 Cache → MongoDB.

Redis Evict / TTL Recovery
If a key is evicted from Redis or expires via TTL, the L1 Sync task automatically restores it from L1 and marks it dirty so the flush task re-persists it to MongoDB. Previously, evicted keys were silently skipped.

Batch Reconciliation
The reconciliation task now processes entries in batches of 50 concurrent MongoDB requests. Previously, all entries were queried simultaneously — on datasets of 1000+ entries this caused uncontrolled request spikes against MongoDB.

O(1) ID Lookup
getDataModelFromId() previously performed a full linear scan (O(n)) over the entire in-memory map. A reverse index (id → key) has been added, making lookups instant regardless of dataset size.


Bug Fixes

  • Data loss on flush failuredirtyKeys.remove() was called before confirming the MongoDB write. If the write failed, the dirty flag was already gone and the entry would never be retried. Fixed: flag is removed only after .get() confirms success.
  • TOCTOU race in removeModel()containsKey() followed by remove() is not atomic; another thread could delete the entry between the two calls. Fixed: direct remove() with return value check.
  • Deadlock risk in reconciliationprocessTask was being called from inside an already-running processTask via thenAccept. Fixed: all reconciliation logic runs within a single task context.
  • addModelFix() leaving Redis empty — the method wrote only to L1, leaving Redis without the key. The next L1 Sync would detect the missing key and trigger a redundant restore cycle. Fixed: both L1 and Redis are written together via writeToL1AndRedis().

Internal Changes

  • idToDataList renamed to keyToModel for clarity
  • updateInternal() renamed to writeToL1AndRedis() to reflect exact behaviour
  • System.out.println replaced with java.util.logging.Logger throughout
  • Sync intervals adjusted: L1 Sync 10s, Auto Flush 15s, Reconciliation 3min

Upgrade Notes

This release is a drop-in replacement. Public API method signatures are unchanged.
addModelFix() behaviour has changed slightly — it now also writes to Redis immediately, which is the correct behaviour and should not affect existing call sites.