fix: invalidate the RedisDict write signature on batch delete

RedisDict.set() skips the write when the payload fingerprint matches the last one this process wrote, so a mutation that goes around set() has to clear that fingerprint. The new batch delete did not, leaving a stale fingerprint behind: the next refresh with identical content is treated as already written and silently skipped, so the hash stays empty.

Renamed pop_many to delete_many. In a dict emulation pop removes and returns; this returns nothing and cannot without an extra HMGET, so the name promised something it does not do. delete_many matches __delitem__ and the HDEL underneath. Its only call site is the session pool reaper, whose behaviour is unchanged: same fields deleted, same batching, same return.
This commit is contained in:
Classic298 2026-08-31 03:44:38 +02:00
parent fabe845337
commit 444676b670
2 changed files with 3 additions and 2 deletions

View file

@ -206,7 +206,7 @@ async def periodic_session_pool_cleanup():
if expired:
log.warning('Reaping %d orphaned session(s) from the session pool', len(expired))
if WEBSOCKET_MANAGER == 'redis':
SESSION_POOL.pop_many(*expired)
SESSION_POOL.delete_many(*expired)
else:
for sid in expired:
SESSION_POOL.pop(sid, None)

View file

@ -115,10 +115,11 @@ class RedisDict:
if cursor == 0:
break
def pop_many(self, *keys):
def delete_many(self, *keys):
"""Delete fields in one HDEL; no keys is a no-op (HDEL rejects an empty field list)."""
if keys:
self.redis.hdel(self.name, *keys)
self._last_signature = None
def set(self, mapping: dict):
if not mapping: