- Shipped
- September 23, 2026 at 10:41 AM UTC
- Author
- Kamo
- Commit
- e696226
getBulkPresence/getBulkLastSeen ran KEYS PRESENCE:*/PRESENCE_LAST_SEEN:* on every call - hit on every presence-socket mount and tab focus - and the 30s sweep ran it twice more, all against the same Redis that holds every *** session. KEYS walks and blocks the entire keyspace; at platform scale that is a full-Redis stall on a request path, not a per-org one. Each of the three now reads a maintained index instead of scanning: - PRESENCE_ORG_INDEX:{orgId} - a ZSET of memberId scored by last heartbeat, written by handleConnect/handleHeartbeat, removed by handleDisconnect's grace-period delete. getBulkPresence reads it directly (org scoping is by construction now, not a per-candidate orgId check); the sweep's member half reads it with ZRANGEBYSCORE to find only plausibly-stale candidates. - PRESENCE_ACTIVE_ORGS - a SET of org ids, so the sweep can visit every org's index without discovering org ids by scanning member data. - **************** - a SET backing getBulkLastSeen the same way. Not swept, same as before: the individual key's own 400-day TTL is still what retires it. - PRESENCE_PUBLIC_INDEX - one flat ZSET for visitor sessions (no org concept, nothing reads them in bulk by org), feeding the sweep's public half. Every per-id hash key (PRESENCE:, PRESENCE_PUBLIC:, PRESENCE_LAST_SEEN:) is unchanged - same fields, same TTLs - and stays the single source of truth for its own state; an index only narrows which ids get looked at; a read or the sweep still checks the real hash before trusting or reporting anything, and self-heals (drops the index entry) if the hash has already outlived it. A revived heartbeat (key expired mid-session) still cannot attribute an org - the same gap the old KEYS+HGET("orgId") scan had, since that path never wrote the field either; only the org-bulk view is affected, unchanged from before. Covered by PresenceBulkLookupTest (new) and PresenceSweepTest (rewritten for the new discovery mechanism, same behavioural pins as before plus a "never calls KEYS" check), mutation-checked: dropping the index write in handleConnect, the self-heal branch in getBulkPresence, and the hasKey guard in the sweep each turn a specific assertion red.
