Skip to content

Migrate cache implementation from PSR Simple Cache to Redis for atomic operations #1804

@coderabbitai

Description

@coderabbitai

Context

This issue tracks the migration of the cache implementation from PSR Simple Cache to Redis to enable atomic operations and eliminate race conditions in cache index management.

Background

In PR #1696, a race condition was identified in the registerCacheKeyForDepartments() method in zmsdb/src/Zmsdb/Useraccount.php. The method uses a non-atomic read-modify-write pattern that can lose cache index entries under concurrent access:

$existing = App::$cache->get($indexKey);  // Read
if (!is_array($existing)) {
    $existing = [];
}
if (!in_array($cacheKey, $existing, true)) {
    $existing[] = $cacheKey;              // Modify
    App::$cache->set($indexKey, $existing); // Write
}

Currently, this is mitigated by a fallback version-bump mechanism that ensures eventual consistency, but it's not optimal for high-concurrency scenarios.

Reference: #1696 (comment)

Proposed Solution

Migrate from PSR-16 Simple Cache to native Redis client (or Redis-backed cache with atomic operations) to enable:

  1. Atomic list operations using Redis commands like SADD for cache index management
  2. Better performance under high concurrency
  3. Additional cache features like TTL per key, atomic counters, etc.

Example atomic implementation:

// Instead of read-modify-write cycle
App::$cache->addToSet($indexKey, $cacheKey);  // Atomic SADD operation

Dependencies

Blocked by: #1799 (refactor issue must be completed first)

Acceptance Criteria

  • Replace PSR Simple Cache interface with Redis client or Redis-backed atomic cache
  • Update registerCacheKeyForDepartments() to use atomic set operations
  • Update invalidateDepartmentCaches() to work with Redis sets
  • Ensure backward compatibility or provide migration path
  • Update documentation and configuration examples
  • Add tests for concurrent cache operations

Additional Notes

Requested by: @ThomasAFink
Related PR: #1696

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions