pypi redis 8.2.0b1

6 hours ago

Changes

✨ Highlights

Client-side caching: tracking modes and metadata-driven eligibility

CacheConfig takes a new tracking_mode option (TrackingMode.PLAIN, OPTIN or OPTOUT). It also takes an optional cache_predicate(command, keys) that decides which eligible replies are stored. With OPTIN or OPTOUT, the server tracks only the keys the client caches. PLAIN is the default and keeps the current behavior. (#4358)

Cache eligibility and cluster routing now come from one source: the command metadata in redis.commands.metadata. A MetadataResolver can be passed with metadata_resolver= to Redis, ConnectionPool and RedisCluster. CacheConfig.DEFAULT_ALLOW_LIST is deprecated and is no longer read. (#4272)

The same resolver decides which commands are safe to route to cluster replicas. This lets module commands, for example from FalkorDB, use replica reads through custom metadata. redis.asyncio.RedisCluster now accepts metadata_resolver= too. READ_COMMANDS is deprecated and is no longer read. (#4265)

Python support

This release drops Python 3.10, which has reached end of life, and adds Python 3.15. (#4489)

🚀 New Features

  • Feat/register custom read commands (#4265)
  • feat: decide client-side cache eligibility from command metadata (#4272)
  • Added CLIENT LIST iterator alternative (#4327)
  • Added support for CELL_SIZE argument for CMS.INITBYDIM and CMS.INITBYPROB (#4341)
  • feat: add OPTIN and OPTOUT tracking modes to client-side caching (#4358)
  • feat: bless commands family (#4362)
  • feat: add set member expiration commands (SEXPIRE family and SADDEX) (#4543)

⚠️ Deprecations

  • feat: decide client-side cache eligibility from command metadata (#4272)

🐛 Bug Fixes

  • test + fix: add sharded pub/sub e2e coverage and fix the client defects it exposed (#4076)
  • Fix return_field ignoring decode_field for aliased fields (#4243)
  • Pass zrevrange key as a list in options["keys"] to match sibling range commands (#4244)
  • fix(asyncio): raise on EOF in can_read() so pools replace server-closed connections (#4260)
  • fix(multidb): stop star-unpacking args in execute_pubsub_method (#4276)
  • fix(lock): preserve zero-timeout locks on renewal (#4282)
  • fix(asyncio): raise ConnectionError when writing to a peer-closed connection (#4288)
  • fix(sentinel): disconnect on read errors by default (#4292)
  • fix: treat InvalidResponse as connection-invalidating even when disconnect_on_error=False (#4293)
  • Clear the in-progress cache entry when a read fails (#4306)
  • fix: raise when only one FILTER_BY_VALUE bound is given (#4310)
  • fix(multidb): pass transaction options as keyword arguments (#4340)
  • Fix CLUSTER SHARDS slots shape differing between RESP2 and RESP3 (#4380)
  • Wait for the pubsub worker before stop() returns (#4400)
  • Decode consumer keys in XINFO STREAM FULL responses on RESP3 (#4401)
  • Keep RESP2 score text when converting RESP3 scores to legacy shapes (#4427)
  • Fix VADD updates with empty attributes (#4430)
  • Return str legacy scores when decode_responses=True (#4432)
  • Do not execute the async utils.pipeline batch after an exception (#4435)
  • Add FUNCTION STATS to the unified and legacy response callbacks (#4453)
  • Bound the SSL handshake by socket_connect_timeout (#4471)
  • Honor field encodings in FT.PROFILE search results (#4475)
  • bug(multidb): Fixed in-use connections to not be forcefully closed on failover (#4481)
  • Return floats from INCREX BYFLOAT with unified responses on RESP2 (#4519)
  • Return floats from MEMORY STATS with unified responses on RESP2 (#4529)
  • Return TS.INFO rules as a list on RESP3 (#4553)

🧰 Maintenance

  • test + fix: add sharded pub/sub e2e coverage and fix the client defects it exposed (#4076)
  • Fix db.client.connection.count metric drifting over time (#4078)
  • perf: cache default response callbacks instead of rebuilding on every client init (standalone sync and async clients) (#4124)
  • Add ASM (Atomic Slot Migration) cluster maintenance-notification scenario tests (#4158)
  • Use hiredis command packing for async connections (#4191)
  • Eliminate GC refcounting cycle on _connect exception (#4195)
  • perf(connection): pipeline the sync connection handshake (#4203)
  • fix: allow EVALSHA in ClusterPipeline (#2914) (#4206)
  • Document that querystring values are not unquoted twice (#4209)
  • docs: add hash examples notebook (#4228)
  • Report test metrics once a night instead of from every CI job (#4229)
  • perf/fix: Use lazy logging in pub/sub push handlers to avoid formatting discarded debug messages (#4231)
  • test: add unit tests for pairs_to_dict and pairs_to_dict_typed (#4234)
  • fix(zadd): correct the mutually-exclusive-option error message (#4235)
  • build(deps): bump rojopolis/spellcheck-github-actions from 0.62.0 to 0.68.0 (#4236 #4304 #4554)
  • build(deps): bump actions/setup-python from 6 to 7 (#4237)
  • build(deps): bump actions/stale from 10 to 11 (#4238)
  • build(deps): bump github/codeql-action from 4 to 4.39.1 (#4239 #4303 #4366 #4555)
  • fix(asyncio): reject connection URLs missing the scheme separator (#4246)
  • fix: release async cluster transaction connections to their real owner (#4254)
  • Fix async cluster release race for closed connections (#4256)
  • fix(lock): preserve token when sync Lock.release() fails (#4258)
  • docs(cluster): say which async ClusterPipeline methods must be awaited (#4264)
  • Assert the reclamation property in the _connect cycle tests (#4267)
  • docs: point multi-database docs at geographic_failover (#4269)
  • docs: fix OpenTelemetry Flask guide URL (#4270)
  • Don't crash parsing CLIENT INFO with '=' or spaces in a field value (#4275)
  • Fix asyncio Connection mutating caller retry_on_error list (#4280)
  • fix(connection): parse retry_on_error URL query as exception classes (#4281)
  • fix: raise ConnectionError when async RESP3 parser reads after disconnect (#4283)
  • test: add unit tests for dict_merge, merge_result and list_keys_to_dict (#4290)
  • Fix typos in example notebooks (#4294)
  • Fix dead links in vector similarity example notebook (#4295)
  • fix(cluster): initialize async Pub/Sub before routing (#4297)
  • Do not lose pool capacity when connection construction fails (#4298)
  • Fix integration tests for Redis Enterprise runs (#4300)
  • Stabilize MultiDB (Active-Active) client and tests (#4301)
  • Stabilize maint notifications tests and add connection diagnostics (#4302)
  • docs: fix fused/duplicated words in core and cluster docstrings (#4311)
  • docs(search): fix 'info an stats about the the' in both ft.info docstrings (#4312)
  • docs: drop duplicated words in sentinel and maint_notifications comments (#4313)
  • fix(asyncio): set lock_name on the errors the async lock raises (#4317)
  • test: run the assertions that sit inside pytest.raises blocks (#4319)
  • Fix OverflowError in exponential backoff during a long outage (#4320)
  • [fix(asyncio)] Refresh cluster topology before retrying MOVED redirects (#4322)
  • Align empty cluster target handling (#4324)
  • Preserve explicit port zero in connection URLs (#4325)
  • docs(search): replace retired redisearch doc links in field docstrings (#4332)
  • fix: 'one of the followings' -> 'one of the following' and fix :param fields (#4333)
  • docs: add the missing 'the' in 'Each call to current method/command' (#4334)
  • Reject bool and out-of-range Connection port (#4335)
  • docs: note that PubSub.listen() returns immediately when nothing is subscribed (#4336)
  • Avoid Python deprecation warnings for Redis commands (#4338)
  • fix(keyspace): parse length-prefixed payloads in the byte domain (#4342)
  • fix(asyncio): close the health check HTTP thread pool on shutdown (#4343)
  • fix: accept numeric string for px in extract_expire_flags (#4344)
  • Fix connection leak in utils.pipeline() on exception (#4345)
  • test(asyncio): align wait_for_message with the sync helper's 0.5 s budget (nightly 8.10/py3.14 unified cells) (#4346)
  • fix(search): forward TIMEOUT 0 in hybrid_search (#4347)
  • fix: reject malformed subkey notifications (#4348)
  • docs: add a pub/sub example notebook (#4349)
  • Return floats from VEMB with unified responses on RESP2 (#4350)
  • Escape the decimal point in the unstring float pattern (#4351)
  • Added health_check_timeout relaxation + E2E tests for MultiDBClient and SCH enabled (#4354)
  • Bind OCSP response to the certificate being validated (#4355)
  • fix(geo): encode GEOSEARCH zeros instead of dropping them (#4356)
  • Fix XPENDING filtering for empty consumer names (#4357)
  • Ignore PyJWT 2.13.0 CVEs in dependency audit until redis-entraid is updated (#4359)
  • Update test images and increase pypy tests timeout (#4360)
  • fix(bf): don't send NONSCALING/NOCREATE when the flag is False (#4364)
  • build(deps): bump pypa/gh-action-pip-audit from 1.0.8 to 1.1.0 (#4365)
  • fix(commands): omit COUNT when count=None in the *MPOP commands (#4367)
  • Generate lock tokens with uuid4 instead of predictable uuid1 (#4368)
  • Adding CVE-2026-103001 to the ignore list (#4369)
  • chore: skip coverage collection and codecov upload in PyPy CI jobs (#4370)
  • Make the test suite collectable and dev requirements installable on Windows (#4371)
  • Fix zero-count limits in search requests (#4373)
  • fix: recognize OFF as false in URL boolean parsing (#4376)
  • fix(asyncio): convert synchronous retry policies (#4381)
  • Fix bf incrby docstring examples to call the real client API (#4382)
  • feat: support RediSearch 8.12 HNSW SQ8 compression in FT.INFO unified parsing (#4386)
  • fix(asyncio): add the missing get_sharded_message alias to PubSub (#4387)
  • fix: cache the redis package version lookup in get_lib_version (#4390)
  • Add keyword-only sleep argument to asyncio Lock.acquire (#4391)
  • fix(asyncio): avoid blocking the event loop during cluster WATCH retries (#4392)
  • fix(csc): refuse user-sent CLIENT TRACKING and RESET on cache-managed connections (#4393)
  • chore: add prepare-for-takeover agent skill for stalled PRs (#4396)
  • Fix async MultiDBClient lifecycle handling when exiting a pipeline context. (#4398)
  • Treat OS-level ETIMEDOUT as a connection error, not a read/write timeout (#4399)
  • fix: isolate default MultiDB retry policies per configuration (#4403)
  • fix: prevent synchronous token startup from deadlocking its event loop (#4405)
  • Fixing some flaky tests (#4407)
  • fix: record db.client.connection.timeouts when BlockingConnectionPool times out (#4409)
  • test: speed up the slowest tests by batching round trips and skipping futile retries (#4410)
  • fix(asyncio): reconnect pooled connections the peer reset while idle (#4412)
  • Fix ZRANGESTORE with an empty destination key (#4413)
  • Fix weighted sorted-set aggregation for mapping inputs (#4414)
  • Do not send NOVALUES from hscan when no_values is False (#4416)
  • Keep connection_class passed to the async ConnectionPool.from_url (#4418)
  • Fix async pipeline error messages embedding the args tuple (#4420)
  • Test fewer Redis versions on pull requests (#4421)
  • test: adding various test optimizations to improve the overall time tests are running (#4422)
  • Run the async Unix socket handshake only once per connect (#4424)
  • perf(utils): optimize @deprecated_args and @experimental_args fast path (#4423) (#4425)
  • Compare OCSP response validity times in UTC, not local time (#4426)
  • Break the ResponseError reference cycle in asyncio read_response (#4434)
  • Add BGSAVE, BGREWRITEAOF and DEBUG OBJECT to the RESP3 unified callbacks (#4436)
  • fix(csc): clone mutable responses to prevent cache corruption on first miss (#4438)
  • Break the startup node error reference cycle in NodesManager.initialize (#4439)
  • Verify the OCSP signer chains to the certificate's issuer (#4441)
  • Add get_connection_kwargs() and get_encoder() to the MultiDB clients (#4442)
  • Treat path=None as the root path in JSON commands (#4444)
  • fix: pace cluster topology refreshes, keep healthy node connections, and stop retrying unreachable clusters (#4448)
  • Run pending MOVING cleanups when a ConnectionPool closes (#4449)
  • Add sharded pub/sub to the asyncio MultiDBClient PubSub (#4450)
  • Accept a list of patterns in the async PubSub.punsubscribe (#4451)
  • Forward ssl_min_version, ssl_ciphers and OCSP options to RedisCluster nodes (#4452)
  • Send LABELS from TS.ALTER when labels is an empty dict (#4455)
  • Treat UNBLOCKED from a demoted master as a connection error (#4457)
  • Fix search querystring negation and optional prefix for multi child nodes (#4460)
  • Bind the stapled OCSP check to the connection's certificate (#4461)
  • Parse boolean OCSP options in connection URLs (#4464)
  • Document BlockingConnectionPool and the default connection limit (#4466)
  • Redact credentials from pipeline error messages (#4467)
  • Enable client-side caching on Unix domain socket connections (#4469)
  • perf(observability): resolve the metrics collector once per configuration (#4472)
  • Skip FT.HYBRID cursor tests on Redis 8.11+ and document the exposed versions (#4473)
  • Keep re-authenticating the other nodes and renewing the token when one AUTH fails (#4479)
  • Keep cluster sharded pub/sub tracking correct after a reconnect drops a pending sunsubscribe (#4483)
  • Mention digit strings in extract_expire_flags error messages (#4484)
  • Fix connection count metrics after fork (#4485)
  • Fix cluster retries after acknowledged WATCH (#4486)
  • test: make the pool lifecycle metric tests assert real teardown and drop a never-run cluster retry test (#4487)
  • ci: report nightly metrics for all suites against the current Redis release (#4488)
  • build: drop Python 3.10 support and add Python 3.15 support (#4489)
  • ci: print container state and Redis server logs when a test job fails (#4490)
  • Recognize the asyncio pipeline in async search commands (#4491)
  • build: bump redis-entraid to 1.2.2 and PyJWT to 2.15.1, drop PyJWT audit ignores (#4492)
  • Reject OCSP responses signed by an expired delegated responder (#4493)
  • fix: return None from HOTKEYS GET without a session on RESP2 and skip SLOTS for an empty SLOTS list (#4495)
  • Return an empty dict from VSIM with scores or attributes on a missing key (#4496)
  • Fail closed on an unauthorized OCSP response instead of retrying (#4497)
  • fix: drain cache invalidations outside the cache lock (#4498)
  • Return the pipeline from search commands that parse their reply (#4499)
  • Parse TS.INFO RESP3 replies that have bytes keys (#4500)
  • Disconnect a pipeline connection when a response callback raises (#4501)
  • fix: record stream lag for unified XREAD responses (#4504)
  • Document how acl_setuser selectors are tokenized (#4506)
  • Reset the pool handler after fork (#4508)
  • Fix blocking async pool checkout during idle reauthentication (#4509)
  • Fix async client context cleanup during cancellation and concurrent re-entry (#4510)
  • Fix decoded RESP3 PubSub PING replies (#4511)
  • Fix private-loop connection reuse in lazy async cluster transactions (#4513)
  • Keep cluster bus ports out of the ephemeral port range in the test containers (#4517)
  • test: make hybrid search load/apply/params test order-independent (#4521)
  • Apply address_remap to MOVED and ASK redirect targets in RedisCluster (#4522)
  • test: run fd exhaustion check in a subprocess instead of pytest-forked (#4525)
  • Add read-path A/B benchmark suite and on-demand Benchmarks workflow (#4526)
  • fix: handle default decoding in VEMB RAW with connection pools (#4527)
  • fix(zrange): add opt-in use_rev keyword to send ZRANGE REV (#4528)
  • fix: parse INFO with non-UTF-8 errorstats when decode_responses=True (#4532)
  • Honor connection_class and connection_pool_class in sync RedisCluster without a URL (#4534)
  • Drop the keys option before running response callbacks in async cluster transactions (#4535)
  • Isolate private-loop parser connections in async cluster transactions (#4537)
  • Parse keyspace notifications for keys that contain a newline (#4538)
  • Try the next sentinel when SENTINEL MASTERS returns an error reply (#4539)
  • Route COMMAND GETKEYSANDFLAGS in cluster mode like COMMAND GETKEYS (#4540)
  • Invalidate client-side cache entries for int and float keys (#4541)
  • Await direct asyncio FT.PROFILE responses while preserving pipeline queuing (#4542)
  • Add observability recorder micro-benchmark to the Benchmarks workflow (#4544)
  • Disconnect in connect_check_health on any handshake failure (#4546)
  • Support clusters that use cluster-preferred-endpoint-type unknown-endpoint (#4547)
  • Fix cluster_myshardid() with decode_responses=True (#4548)
  • Fix empty keys in keyspace notifications (#4549)
  • Split CLIENT LIST records on newline only (#4556)
  • perf(asyncio): gate pipeline packing offload on batch size (#4561)
  • Stop RedisCluster retries from releasing a connection twice (#4564)
  • Flush the client-side cache when a pool resets after fork (#4566)
  • Fix search results with a field named payload or score (#4567)

We'd like to thank all the contributors who worked on this release!
@verdie-g @madhavcodez @sakshichitnis27 @rschlaikjer @ahmed5145 @winklemad @Brumbelow @Classic298 @eeshsaxena @ritsth @uttam12331 @Arunendra21 @LubuSeb @ckarnell @SantoshDhaladhuli @clemenslosbichler-cloud @JiuYue0820 @pouyashahrdami @leilei3167 @daleselaji-dev @abersheeran @dylanpulver @UgaTheDev @Zeming-Yuan @nightcityblade @youdie006 @simpleqt @sachhg @h1r0-tech @GruffElixir @niukanen1 @Pitchfork-and-Torch @Nappuccino-tlg @Shubham-Padkonde @kratos0718 @glaziermag @Rodrigo-Palma @kokokoXUY @wenqiw777 @januththedev @Vidya-m78 @00200200 @LindseyZ1205 @dltsum @fallintoplace @vineoy @AmaedaQ @lazerg @HassanRady @pickedbrian @Shaisolaris @Elyahou @HardMax71 @fhgffy @halilunay @austenstone @pheonix14 @novain-shibu @Ganesh1729-ui @spicysharkco @abhishekacharya200 @pcbeingused333 @RaphaelFakhri @alviss7 @sebxt @taltal-beep @mohsinaliwork686-rgb @kmecpp @JackyHsu-X @ekanshul @AliAbouelazm @nk-batman21 @parijat1222q @umtong @Vmnebula @ericdelorefice @liuyinchu @mirzasnowy @chrikrah @BlueX888 @arxhr007 @baraiz @AG0708 @lh0156 @kiryazovi-redis @vlady-kotsev @bobymicroby @vladvildanov @elena-kolevska @petyaslavova

Don't miss a new redis release

NewReleases is sending notifications on new releases.