Skip to content

feat: v0.1.0 - sets, counters, TTL introspection, list ops + memory-mode TTL fixes#11

Merged
askalf merged 1 commit into
masterfrom
feat/v0.1.0
Jun 10, 2026
Merged

feat: v0.1.0 - sets, counters, TTL introspection, list ops + memory-mode TTL fixes#11
askalf merged 1 commit into
masterfrom
feat/v0.1.0

Conversation

@askalf

@askalf askalf commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Grows the surface from "cache + pub/sub + rate limit" to most of the day-to-day Redis command set, and makes memory-mode TTL handling correct for every key type. Ships the v0.1.0 bump, so merging this auto-releases to npm.

Added

  • Sets: sadd / srem / smembers / sismember / scard
  • Counters: incr / decr / incrby / hincrby (memory mode counts missing keys from 0, throws Redis's "value is not an integer or out of range" on non-integer values)
  • TTL introspection: ttl (-2 / -1 sentinels, seconds rounded up) and pttl
  • Lists: lpush / lpop / rpop / llen; popping the last element deletes the key like real Redis
  • mget, zscore (score as string, matching ioredis), zrem, zrangebyscore (-inf/+inf + exclusive (n bounds)
  • set accepts trailing EX <seconds> / PX <ms>; memory mode throws on unsupported option tokens (NX/XX/KEEPTTL) instead of silently diverging from ioredis mode

Fixed

  • expire/pexpire now work on every key type in memory mode — TTLs moved to a single expirations map covering strings, hashes, lists, sets, and zsets (previously they silently no-oped on anything that wasn't a plain string). Reads lazily evict; the sweep covers all stores; emptied collections drop the key and its TTL.
  • keys(pattern) scans every store (only saw string keys before); del/exists cover sets.
  • lrange/zrange handle negative indexes properly (only stop === -1 was special-cased).
  • zremrangebyscore no longer turns '(5' into NaN — which used to remove every member; the shared bound parser rejects malformed bounds loudly.
  • Plain set(key, value) clears an existing TTL (Redis semantics — no implicit KEEPTTL).

Changed

  • IoRedisAdapter.duplicate() no longer constructs a throwaway Redis instance.

Tests

36/36 (was 20) — sets, counters + non-integer throw, ttl/pttl incl. real-time pexpire expiry, expire-on-hash/list/zset/set, set EX/PX + unsupported-option throw + TTL-clear, negative-index ranges, exclusive-bound regression, mget with gaps, duplicate() sharing the new stores.

…l-types fix

- New commands on IRedisAdapter + both adapters: sadd/srem/smembers/
  sismember/scard, incr/decr/incrby/hincrby, ttl/pttl, lpush/lpop/
  rpop/llen, mget, zscore/zrem/zrangebyscore, set with EX/PX options.
- Memory-mode TTL refactor: one expirations map covers every key type
  (expire/pexpire previously no-oped on hashes/lists/zsets); reads
  lazily evict; sweep covers all stores; emptied collections delete
  the key and its TTL like real Redis.
- keys() scans every store, not just strings; del/exists cover sets.
- lrange/zrange handle negative indexes properly; zremrangebyscore no
  longer turns '(5' into NaN-removes-everything (shared bound parser
  with -inf/+inf and exclusive bounds, throws on garbage).
- IoRedisAdapter.duplicate() no longer constructs a throwaway Redis
  instance.
@askalf askalf merged commit 2bea49b into master Jun 10, 2026
7 checks passed
@askalf askalf deleted the feat/v0.1.0 branch June 10, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant