Convert Redis Set ID Indices to Sorted Sets for Stable Pagination & Deterministic Ordering - #105
Merged
prodbycorne merged 1 commit intoJul 20, 2026
Conversation
Contributor
Author
|
Hi, please can a maintainer approve the workflow and review this PR? Thank you. |
5 tasks
Merged
3 tasks
boluwacodes
added a commit
to boluwacodes/smartdrop-backend
that referenced
this pull request
Jul 22, 2026
scanIds() was converted from SSCAN (plain set) to ZSCAN (sorted set) by SmartDropLabs#105, but this one assertion still checked mockRedis.sscan instead of mockRedis.zscan, so it silently asserted 0 > 1 was never reached via the real code path and would have passed for the wrong reason.
boluwacodes
added a commit
to boluwacodes/smartdrop-backend
that referenced
this pull request
Jul 22, 2026
SmartDropLabs#105 converted apiKeys.js's id index from a plain Set (sadd/srem/ smembers) to a sorted Set (zadd/zrem/zrevrange) for stable pagination, but this test's inline Redis mock was never updated, so createKey() threw "redis.zadd is not a function" for every test that creates a key.
boluwacodes
added a commit
to boluwacodes/smartdrop-backend
that referenced
this pull request
Jul 22, 2026
Same missing zadd/zrem/zrevrange/zcard/zscan gap as auth.test.js - airdrops.js's id index and expiry scan also moved to a sorted set under SmartDropLabs#105. Also removes leftover console.log debugging statements someone left in while chasing this same failure.
boluwacodes
added a commit
to boluwacodes/smartdrop-backend
that referenced
this pull request
Jul 22, 2026
alerts.js's id index also moved to a sorted set under SmartDropLabs#105 (zadd/zrevrange/zcard/zrem); this route-level test's Redis mock only had smembers, so GET /api/v1/alerts 500'd before ever reaching the pagination assertions it's meant to check.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #82
Summary
This PR replaces Redis Set-based ID indices with Redis Sorted Sets to provide stable, deterministic ordering for paginated list endpoints.
Previously, the affected services retrieved all IDs using
SMEMBERSand performed pagination by slicing the resulting array in application code. Since Redis Sets do not guarantee iteration order, clients could encounter duplicate or missing items across pages, even when no writes occurred between requests.This change adopts Redis Sorted Sets scored by creation timestamp, ensuring consistent newest-first ordering while preserving the existing public API.
Changes
SADDwithZADDusingDate.now()as the score.SMEMBERSand application-side slicing withZREVRANGEfor Redis-native pagination.SREMwithZREM.ids.lengthwithZCARD.Validation
Notes
Items created within the same millisecond may receive identical scores. In those cases, Redis deterministically orders members lexicographically by ID, providing stable pagination even though strict creation order for same-millisecond inserts is not guaranteed.
If existing deployments already store these keys as Redis Sets, a migration or clean cutover is required before deployment to avoid Redis
WRONGTYPEerrors.