Skip to content

fix(sandbox/storage): clean stale team-index entries when expiration-index orphan is swept - #3568

Closed
AdaAibaby wants to merge 2 commits into
e2b-dev:mainfrom
AdaAibaby:fix/sandbox-storage-stale-team-index-cleanup
Closed

fix(sandbox/storage): clean stale team-index entries when expiration-index orphan is swept#3568
AdaAibaby wants to merge 2 commits into
e2b-dev:mainfrom
AdaAibaby:fix/sandbox-storage-stale-team-index-cleanup

Conversation

@AdaAibaby

Copy link
Copy Markdown
Contributor

When ExpiredItems sweeps a ZSET member whose sandbox key is gone (orphaned entry), it only removed the ZSET member but left the corresponding sandboxID in the per-team SET index. These stale entries accumulate indefinitely because no other code path cleans the team index for absent sandbox keys:

  • TeamItems / fetchSandboxBatch silently skip nil MGET results
  • The healer only fills missing ZSET members, never prunes the team index
  • Remove() / removeSandboxScript cleans the team index atomically, but only runs on the normal Remove call path, not on external key loss

Observed impact: teams with high sandbox churn and Redis key eviction (or restarts without full persistence) accumulated thousands of stale SET members, inflating team-index memory and slowing TeamItems SMEMBERS + MGET scans.

Fix: when an orphaned ZSET member is found (MGET returned nil), also SREM the sandboxID from the team index. Safety: MGET just confirmed the sandbox key is absent, so we cannot unindex a live sandbox. A concurrent Add that races our SREM will SADD the sandboxID back immediately after, so the worst outcome is a brief gap in TeamItems results for one eviction cycle.

…index orphan is swept

When ExpiredItems sweeps a ZSET member whose sandbox key is gone (orphaned
entry), it only removed the ZSET member but left the corresponding sandboxID
in the per-team SET index. These stale entries accumulate indefinitely because
no other code path cleans the team index for absent sandbox keys:
- TeamItems / fetchSandboxBatch silently skip nil MGET results
- The healer only fills missing ZSET members, never prunes the team index
- Remove() / removeSandboxScript cleans the team index atomically, but only
  runs on the normal Remove call path, not on external key loss

Observed impact: teams with high sandbox churn and Redis key eviction (or
restarts without full persistence) accumulated thousands of stale SET members,
inflating team-index memory and slowing TeamItems SMEMBERS + MGET scans.

Fix: when an orphaned ZSET member is found (MGET returned nil), also SREM the
sandboxID from the team index. Safety: MGET just confirmed the sandbox key is
absent, so we cannot unindex a live sandbox. A concurrent Add that races our
SREM will SADD the sandboxID back immediately after, so the worst outcome is a
brief gap in TeamItems results for one eviction cycle.
@AdaAibaby
AdaAibaby force-pushed the fix/sandbox-storage-stale-team-index-cleanup branch from 2b270e6 to 6882627 Compare August 14, 2026 04:04
@AdaAibaby AdaAibaby closed this Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants