@@ -1077,12 +1077,11 @@ cleanup_test_objects() {
10771077
10781078generate_report () {
10791079 log_header " Generating Report"
1080-
1080+
10811081 local cache_stats=$( get_cache_stats)
10821082 local cache_hits=$( echo " $cache_stats " | grep -o ' "hits":[0-9]*' | cut -d: -f2)
10831083 local cache_misses=$( echo " $cache_stats " | grep -o ' "misses":[0-9]*' | cut -d: -f2)
10841084 local cache_size=$( echo " $cache_stats " | grep -o ' "length":[0-9]*' | cut -d: -f2)
1085- local cache_invalidations=$( echo " $cache_stats " | grep -o ' "invalidations":[0-9]*' | cut -d: -f2)
10861085
10871086 cat > " $REPORT_FILE " << EOF
10881087# RERUM Cache Metrics & Functionality Report
@@ -1105,7 +1104,6 @@ generate_report() {
11051104| Cache Misses | ${cache_misses:- 0} |
11061105| Hit Rate | $( echo " $cache_stats " | grep -o ' "hitRate":"[^"]*"' | cut -d' "' -f4) |
11071106| Cache Size | ${cache_size:- 0} entries |
1108- | Invalidations | ${cache_invalidations:- 0} |
11091107
11101108---
11111109
@@ -1315,7 +1313,7 @@ The cache layer provides:
13151313In production, monitor:
13161314- **Hit rate**: Target 60-80% for optimal benefit
13171315- **Evictions**: Should be minimal; increase cache size if frequent
1318- - **Invalidation count **: Should correlate with write operations
1316+ - **Cache size changes **: Track cache size over time to understand invalidation patterns
13191317- **Response times**: Track p50, p95, p99 for all endpoints
13201318
13211319### ⚙️ Configuration Tuning
@@ -2237,28 +2235,48 @@ main() {
22372235 # Get starting state at beginning of Phase 5
22382236 local stats_before_phase5=$( get_cache_stats)
22392237 local starting_cache_size=$( echo " $stats_before_phase5 " | grep -o ' "length":[0-9]*' | sed ' s/"length"://' )
2240- local invalidations_before_phase5=$( echo " $stats_before_phase5 " | grep -o ' "invalidations":[0-9]*' | sed ' s/"invalidations"://' )
2241-
2238+ local starting_evictions=$( echo " $stats_before_phase5 " | grep -o ' "evictions":[0-9]*' | sed ' s/"evictions"://' )
2239+
2240+ # Track invalidations ourselves (app doesn't track them)
2241+ # Invalidations = cache size decrease from write operations
2242+ local total_invalidations=0
2243+
22422244 log_info " === PHASE 5 STARTING STATE ==="
22432245 log_info " Starting cache size: $starting_cache_size entries"
2244- log_info " Invalidations before Phase 5: $invalidations_before_phase5 "
22452246 log_info " Phase 3 filled cache with queries matching Phase 5 write operation types"
22462247 log_info " Each write operation should invalidate multiple cache entries"
2248+ log_info " Test will calculate invalidations as cache size decrease per write operation"
22472249
22482250 echo " [INFO] Running write endpoint tests..."
22492251
22502252 # Cache is already full from Phase 3 - reuse it without refilling
22512253
2252- # Helper function to log cache changes
2254+ # Helper function to log cache changes and calculate invalidations
2255+ # Write operations don't add cache entries, so size decrease = invalidations
2256+ local size_before=$starting_cache_size
2257+
22532258 track_cache_change () {
22542259 local operation=$1
22552260 local stats=$( get_cache_stats)
2256- local size=$( echo " $stats " | grep -o ' "length":[0-9]*' | sed ' s/"length"://' )
2257- local invalidations=$( echo " $stats " | grep -o ' "invalidations":[0-9]*' | sed ' s/"invalidations"://' )
2261+ local size_after=$( echo " $stats " | grep -o ' "length":[0-9]*' | sed ' s/"length"://' )
22582262 local evictions=$( echo " $stats " | grep -o ' "evictions":[0-9]*' | sed ' s/"evictions"://' )
2259- local sets=$( echo " $stats " | grep -o ' "sets":[0-9]*' | sed ' s/"sets"://' )
2260-
2261- echo " [CACHE TRACK] After $operation : size=$size , invalidations=$invalidations (Δ+$(( invalidations - invalidations_before_phase5 )) ), evictions=$evictions , sets=$sets " >&2
2263+
2264+ # Calculate invalidations for this operation
2265+ # Write operations don't add cache entries, so size decrease = invalidations only
2266+ local operation_invalidations=$(( size_before - size_after))
2267+
2268+ # Ensure non-negative
2269+ if [ $operation_invalidations -lt 0 ]; then
2270+ operation_invalidations=0
2271+ fi
2272+
2273+ # Accumulate total
2274+ total_invalidations=$(( total_invalidations + operation_invalidations))
2275+
2276+ echo " [CACHE TRACK] After $operation : size=$size_after (Δ-$operation_invalidations invalidations), evictions=$evictions , total_invalidations=$total_invalidations " >&2
2277+
2278+ # Update size for next operation
2279+ size_before=$size_after
22622280 }
22632281
22642282 # DEBUG: Log cache state before each write test
@@ -2286,34 +2304,41 @@ main() {
22862304
22872305 test_delete_endpoint_full
22882306
2289- log_info " Waiting for cache invalidations and stats to sync across all PM2 workers..."
2307+ log_info " Waiting for cache stats to sync across all PM2 workers..."
22902308 log_info " Stats sync every 5 seconds - waiting 12 seconds to ensure at least two sync cycles complete..."
22912309 sleep 12
2292-
2310+
22932311 local stats_after_phase5=$( get_cache_stats)
22942312 local final_cache_size=$( echo " $stats_after_phase5 " | grep -o ' "length":[0-9]*' | sed ' s/"length"://' )
2295- local invalidations_after_phase5=$( echo " $stats_after_phase5 " | grep -o ' "invalidations":[0-9]*' | sed ' s/"invalidations"://' )
2296-
2297- local total_invalidations=$(( invalidations_after_phase5 - invalidations_before_phase5 ))
2298- local actual_entries_removed=$(( starting_cache_size - final_cache_size))
2299-
2300- local total_invalidations=$(( invalidations_after_phase5 - invalidations_before_phase5 ))
2313+ local final_evictions=$( echo " $stats_after_phase5 " | grep -o ' "evictions":[0-9]*' | sed ' s/"evictions"://' )
2314+
23012315 local actual_entries_removed=$(( starting_cache_size - final_cache_size))
2316+ local total_evictions=$(( final_evictions - starting_evictions))
2317+
2318+ # total_invalidations was calculated incrementally by track_cache_change()
2319+ # Verify it matches our overall size reduction (should be close, minor differences due to timing)
2320+ if [ $total_invalidations -ne $actual_entries_removed ]; then
2321+ local diff=$(( actual_entries_removed - total_invalidations))
2322+ if [ ${diff# -} -gt 2 ]; then # Allow ±2 difference for timing
2323+ log_warning " Invalidation count variance: incremental=$total_invalidations , overall_removed=$actual_entries_removed (diff: $diff )"
2324+ fi
2325+ fi
23022326
23032327 echo " "
23042328 log_info " === PHASE 5 FINAL RESULTS ==="
23052329 log_info " Starting cache size: $starting_cache_size entries (after adding 5 test queries)"
23062330 log_info " Final cache size: $final_cache_size entries"
2307- log_info " Actual entries removed: $actual_entries_removed entries"
2331+ log_info " Total cache size reduction: $actual_entries_removed entries"
2332+ log_info " Calculated invalidations: $total_invalidations entries (from write operations)"
2333+ log_info " LRU evictions during phase: $total_evictions (separate from invalidations)"
23082334 log_info " "
23092335 log_info " === PHASE 5 CACHE ACCOUNTING ==="
23102336 log_info " Initial state: ${starting_cache_size} entries"
23112337 log_info " - Cache filled to 1000 in Phase 3"
23122338 log_info " - Added 5 query entries for write tests (matched test object types)"
2313- log_info " - Starting invalidations: ${invalidations_before_phase5} "
23142339 log_info " "
23152340 log_info " Write operations performed:"
2316- log_info " - create: 100 operations (no existing data, minimal invalidation )"
2341+ log_info " - create: 100 operations (minimal invalidation - no existing data)"
23172342 log_info " - update: 50 operations (invalidates id:*, history:*, since:*, matching queries)"
23182343 log_info " - patch: 50 operations (invalidates id:*, history:*, since:*, matching queries)"
23192344 log_info " - set: 50 operations (invalidates id:*, history:*, since:*, matching queries)"
@@ -2322,28 +2347,21 @@ main() {
23222347 log_info " - delete: 50 operations (invalidates id:*, history:*, since:* for each)"
23232348 log_info " "
23242349 log_info " Final state: ${final_cache_size} entries"
2325- log_info " - Entries removed : ${actual_entries_removed } "
2326- log_info " - Invalidations recorded : ${total_invalidations } "
2327- log_info " - Final invalidations : ${invalidations_after_phase5 } "
2350+ log_info " - Invalidations from writes : ${total_invalidations } "
2351+ log_info " - LRU evictions (separate) : ${total_evictions } "
2352+ log_info " - Total size reduction : ${actual_entries_removed } "
23282353 echo " "
23292354
2330- # Validate that invalidations and removals are in the expected range
2355+ # Validate that calculated invalidations are in the expected range
23312356 if [ -n " $final_cache_size " ] && [ -n " $total_invalidations " ]; then
2332- # Calculate difference between invalidations and actual removals
2333- local invalidation_diff=$(( total_invalidations - actual_entries_removed))
2334- local invalidation_diff_abs=${invalidation_diff# -} # Absolute value
2335-
2336- # Important: invalidations count entries actually deleted from cache
2337- # actual_entries_removed may be larger because it includes:
2338- # - Invalidations (entries deleted)
2339- # - LRU evictions (entries removed due to cache limits)
2340- # - Entries that didn't exist (e.g., id:* keys never cached)
2341- #
2357+ # total_invalidations = cumulative cache size decrease from each write operation
2358+ # This represents entries removed by invalidation logic during writes
2359+
23422360 # For DELETE operations:
23432361 # - Each DELETE tries to invalidate 3 keys: id:*, history:*, since:*
23442362 # - But id:* only exists if /id/:id was called for that object
2345- # - history:* and since:* always exist ( created during reads)
2346- # - So we expect ~2 invalidations per DELETE (not 3)
2363+ # - history:* and since:* are created during read operations
2364+ # - So we expect ~2 invalidations per DELETE on average (not 3)
23472365
23482366 # Calculate expected invalidations based on test operations
23492367 local num_deletes=50
@@ -2366,22 +2384,25 @@ main() {
23662384 log_info " Note: Variance can occur if some objects were cached via /id/:id endpoint"
23672385 fi
23682386
2369- # Additional check for suspiciously low invalidation counts (stats sync issue)
2387+ # Additional check for suspiciously low invalidation counts
23702388 if [ $total_invalidations -lt 25 ]; then
23712389 log_warning " ⚠️ Invalidation count ($total_invalidations ) is lower than expected minimum (~25)"
2372- log_info " This is likely due to PM2 cluster stats aggregation timing"
2373- log_info " Cache behavior is correct (${actual_entries_removed} entries removed), but stats under-reported"
2374- log_info " Note: Stats sync wait time is 12s - if this warning persists, check atomic increment implementation"
2390+ log_info " Possible causes:"
2391+ log_info " - Write operations may not have matched many cached queries"
2392+ log_info " - Phase 3 cache fill may not have created many matching entries"
2393+ log_info " - Total size reduction: ${actual_entries_removed} , Invalidations tracked: ${total_invalidations} "
23752394 fi
2376-
2377- # Verify the relationship: actual_entries_removed >= total_invalidations
2378- # (removals include invalidations + evictions + non-existent keys)
2379- if [ $actual_entries_removed -ge $total_invalidations ]; then
2380- log_success " ✅ Cache behavior correct: $actual_entries_removed entries removed ≥ $total_invalidations invalidations"
2381- log_info " Difference ($invalidation_diff_abs ) includes: LRU evictions, non-existent keys, or cluster sync timing"
2395+
2396+ # Verify invalidations are reasonable (should be most of the size reduction)
2397+ # Note: Evictions happen asynchronously during reads, not during writes
2398+ # So invalidations should be close to total size reduction
2399+ if [ $total_invalidations -eq $actual_entries_removed ]; then
2400+ log_success " ✅ All cache size reduction from invalidations: $total_invalidations entries"
2401+ elif [ $(( actual_entries_removed - total_invalidations)) -le 5 ]; then
2402+ log_success " ✅ Most cache reduction from invalidations: $total_invalidations of $actual_entries_removed entries"
23822403 else
2383- log_warning " ⚠️ Unexpected: fewer entries removed ( $actual_entries_removed ) than invalidations ( $total_invalidations ) "
2384- log_info " This may indicate an issue with invalidation tracking "
2404+ log_info " ℹ️ Cache reduction: $total_invalidations invalidations, $actual_entries_removed total removed "
2405+ log_info " Difference may be due to concurrent operations or timing between measurements "
23852406 fi
23862407
23872408 # Report cache size reduction
0 commit comments