Dragonfly v1.39.0
This release delivers a significant leap in full-text search capability — FT.HYBRID fuses vector similarity with text queries, exact phrase matching with slop arrives, Porter stemming is on by default for TEXT fields, and BM25STD/TFIDF scoring with WITHSCORES support rounds out a deeply improved search engine. Performance improves across the board: PubSub reply batching cuts syscalls by 24–70% and raises throughput up to +12% RPS, INFO REPLICATION becomes fully lock-free, and a new ShardedHashMap replaces the global RCU ChannelStore for pub/sub. Security is tightened with multiple Lua sandbox hardening patches, RESP injection prevention, and PII-safe error logging. Tiered hashes are now mutable. A significant sweep of zombie-key cleanup fixes closes a class of bugs where lazy field expiry across SORT, ZUNIONSTORE, ZINTERSTORE, SHRINK, and hash TTL commands left empty containers in the keyspace.
Highlights
- Added
FT.HYBRIDcombining full-text and vector similarity search with LINEAR and RRF score fusion strategies, capping a major release cycle of search improvements (#7420) - PubSub, Monitor, and Invalidation replies are now batched per wakeup, delivering up to +12% RPS and 24–70% fewer syscalls at pipeline depths 1–500 (#7479)
- Tagged chunk serialization splits large objects across snapshot and replication boundaries so they can be reassembled correctly even with interleaved journal entries (#7416, #7070)
Search
- Adds
FT.HYBRIDcombining full-text and VSIM search via LINEAR (ALPHA/BETA weighted sum of normalized scores) and RRF (Reciprocal Rank Fusion) strategies, with HNSW KNN and range-based vector queries,YIELD_SCORE_ASaliasing, LOAD projection, andFT.PROFILEsupport (#7420) - Adds exact phrase queries (
"hello world") and approximate phrase matching with slop ("..."~N), backed by per-document token positions stored in compressed posting lists; BM25 scoring updated for phrase semantics (#7319) - TEXT fields now apply Porter stemming by default via the vendored Snowball/libstemmer library; per-field
NOSTEM, index-levelLANGUAGE(defaultenglish), and per-documentLANGUAGE_FIELDare all supported;FT.INFOsurfaces the new flags (#7295) - Adds BM25STD (Okapi BM25) relevance scoring engine with per-field TF and document-length tracking for accurate normalization; results can be ranked when a scorer is activated (#7101)
- Adds
TFIDF(TF × ln(N/n)) andTFIDF.DOCNORM(additionally normalized by field length) as new scorer options forFT.SEARCH,FT.PROFILE, andFT.AGGREGATE; scorer dispatch refactored to a function-pointer table (#7200) FT.SEARCHnow supportsWITHSCORESandSCORERparameters;FT.AGGREGATEgainsADDSCORESto inject a__scorefield enabling downstream GROUPBY/SORTBY/REDUCE on relevance (#7181)- HNSW vector index memory is now tracked in the
search_usedmemory class and reported indragonfly_memory_used_bytesvia an atomic capacity-based footprint counter (#7205)
Performance
- PubSub, Monitor, and Invalidation control-path replies are now accumulated in the send buffer and flushed together per wakeup rather than one
sendmsgper message; single-message wakeups still flush immediately [+3% RPS at pipeline=1, +12% at pipeline=10, −24% to −70% syscalls at pipeline=1–500] (#7479) - INFO REPLICATION and replica memory stats are now served lock-free via per-proactor thread-local snapshots updated on every mutation, eliminating global mutex and per-replica shared-lock fan-out (#7348)
- Replaced the global RCU-based ChannelStore with a
ShardedHashMap(16 independent shard locks), removing the pool-wide broadcast on every subscribe/unsubscribe (#7174) NotifyWatchQueueexits in O(1) when a watched key is absent (previously O(N) over all waiters), directly benefiting BLPOP, BZPOPMIN, and XREAD workloads (#7225)- Long-running container iteration commands (LRANGE, SMEMBERS, ZRANGE, HGETALL, etc.) now yield the shard fiber periodically; configurable via
--container_iteration_yield_interval_usec(default 500 µs, 0 to disable) (#7391) - Integrates OAHSet as an alternative in-memory set backend selectable via
--use_oah_set; threaded through RDB save/load, async deletion, defragmentation, and SHRINK (#7246) - Adds foundational zero-copy GET infrastructure to CompactObj and LargeString:
TryBorrow()returns an encoded view with Copy-on-Write semantics; a thread-local pin registry defers buffer deallocation until all readers finish (#7412) - Connections that occasionally receive large commands now trim parse buffers exceeding 256 KiB at more than 2× actual utilization, preventing permanent oversized memory holds (#7378)
Replication
- Adds
serialization_tagged_chunksflag enabling the RDB serializer to split large entries into tagged chunks with envelope IDs; compression is applied per-blob; a related list-decoding crash during chunked load is also fixed (#7416) - Implements tagged chunk loading in the RDB loader with per-stream continuation state, supporting interleaved chunks from different objects and cross-database-boundary reassembly (#7070)
- Four new Prometheus metrics are now emitted on replica instances at
/metrics:dragonfly_master_link_status,dragonfly_master_last_io_seconds_ago,dragonfly_sync_in_progress, anddragonfly_slave_repl_offset(#7069)
Cluster
- Adds
--cluster_coordinator_connect_timeout_msand--cluster_coordinator_response_timeout_msflags to control coordinator-to-shard timeouts (previously hard-coded at 3000 ms) (#7221) - Cluster config validation now rejects invalid migration configurations at parse time: wrong target masters, duplicate targets, empty or out-of-range slot sets, and overlapping migration ranges (#7210)
Commands
CLIENT LISTnow supportsTYPE <normal|master|replica|slave|pubsub>andID <id> [id …]filter arguments; outbound replication links are surfaced asTYPE masterentries;CLIENT KILL IDon a master-link ID returns a descriptive error directing users toREPLICAOF NO ONE(#7377)DEBUG TRAFFICnow supports per-listener recording (LISTENER <main|memcache|admin>), full Memcache protocol capture and replay (SET/GET/CAS/INCR/GAT/etc. with flags, expiry, and CAS tokens), and a v3 file format; v2 files remain readable (#7192)DEBUG TRAFFIC START <path> REPLICArecords the replication stream received by a replica from its master; fails with a clear error on standalone/master instances (#7217)BF.SCANDUMPiteratively exports a Scalable Bloom Filter in chunks of up to 16 MiB, returning(cursor, data)pairs untilcursor=0signals end-of-stream (#7092)BF.LOADCHUNKreconstructs an SBF from chunks produced byBF.SCANDUMP, completing the SCANDUMP/LOADCHUNK round-trip; guards prevent other BF commands from operating on a partially-loaded filter (#7169)BGSAVEnow accepts the optionalSCHEDULEsubcommand (case-insensitive) for Redis client compatibility; concurrent saves are still rejected rather than queued (#7286)dfly_benchgains--json_out_fileto write a memtier_benchmark-compatible latency JSON report including per-operation aggregate stats (count, ops/sec, average/min/max, p50/p99/p99.9) and a per-second time-series (#7269)
Security
- The Lua
load()built-in is now wrapped to enforce text-only mode ("t"), closing a sandbox escape vector where a malicious script could supply binary Lua bytecode to bypass restrictions (#7376) - Lua sandbox hardened:
rawset,setmetatable, andgetmetatableare overridden to block access to_Gand all global library tables; guard metatables are attached to prevent replacement or corruption across script executions (#7370) - Error logs from failed commands no longer include user-supplied PII: arguments are truncated at 128 bytes with a byte-count suffix, at most 31 args are logged, EVAL KEYS/ARGV are omitted, and AUTH/ACL subcommands are fully redacted (#7338)
INFO ACLsection added, exposing aggregate registry metrics (acl_num_users, password/glob counts, estimatedacl_total_bytes) maintained incrementally without holding the registry write lock (#7149)
Cloud & Storage
- S3 snapshot storage is now available in all builds using helio's native S3 client by default; the AWS SDK backend remains available via
WITH_AWS+--s3_use_helio_client=false; builds withoutWITH_AWSno longer exit ons3://paths (#7180) - Azure Blob Storage snapshot backend fully implemented:
az://URIs are correctly routed,OpenWriteFile/OpenReadFileuse thecloud::azureAPI, and cursor-based pagination fixes truncation for large buckets (#7131) - Hash write commands (HSET, HDEL) now operate on hashes offloaded to tiered (disk-backed) storage: the serialized listpack is read from disk, mutated in-place, and re-stashed with I/O backpressure (#6085)
- S3 endpoint override (e.g. for MinIO) is now passed directly to
AwsCredsProviderinstead of settingAWS_S3_ENDPOINTin the process environment, eliminating side effects for other processes (#7408)
Bug Fixes
Replication & Persistence
- Fixed
slave_repl_offsetreporting zero inINFO REPLICATIONwhen replicating from a Redis/Valkey master; offset is now correctly populated fromrepl_offs_(#7517) - Fixed a TOCTOU race where a DflyConn_ fiber could violate the serializer's fiber-identity check during BGSAVE while Lua EVAL scripts ran concurrently (#7499)
- Fixed single-shard batch scheduling (
ScheduleBatchInShard) allowing a journal DEL entry to execute before the RDB loader finished creating the key on a shard (#7507) - Fixed SBF (Scalable Bloom Filter) serialization mismatch where
SaveStringencoding was read back as raw bytes, crashing Dragonfly inRenamer::FinalizeRenameon COPY/DUMP (#7475) - Fixed data loaded via
DFLY LOADnot propagating to replicas; the journal ring buffer is now cleared and reconnecting replicas are forced into full sync (#6740) - Fixed slot MOVED redirections becoming corrupted after replica takeover due to
REPLCONF CLIENT-IDsending the replica's internal ID instead of its cluster node ID (#7263) - Fixed a race in cluster slot migration restart where
StartNewSlotMigrationswas called before stale slot data was flushed, causing incomingDFLYMIGRATE FLOWwrites to be wiped (#7333) - Fixed a SIGSEGV during HNSW index replication where per-shard restoration raced with new HSET operations on still-restoring shards; a three-state lifecycle (kProhibit → kRestoring → kBuilding) now defers all graph mutations until all shards complete (#7126)
Security & Lua
- Fixed a RESP protocol injection vulnerability where
redis.error_reply()/redis.status_reply()strings containing\r\ncould inject arbitrary frames into the response stream (#7332) - Fixed
dragonfly.randstr()accepting unbounded arguments; input is now validated for count (1–32768), size (1–16 MiB), and type (#7368) - Fixed
EVAL/EVALSHAcrashing with a CHECK abort on negative or non-numericnumkeysarguments (e.g."-0") instead of returning an error reply (#7203)
Search
- Fixed full-text search scoring (BM25, TF-IDF, TFIDF.DOCNORM) using per-shard document stats instead of global aggregates, causing non-deterministic top-K rankings on multi-shard deployments; a two-phase stats-collection pass now precedes the search (#7250)
- Fixed TEXT field tokenization not honoring backslash escapes (e.g.
\.,\-,\:) symmetrically at index time and query time, causing escaped-punctuation queries to fail to match (#7438) - Fixed a crash during SAVE when FT.SEARCH lazy field expiry left behind an empty zombie hash key;
StringMapAccessor's destructor now deletes the key if the hash is empty after access (#7166)
Commands & Data Structures
RESTOREnow performs deep (entry-by-entry) integrity validation on listpack, intset, quicklist, and stream payloads, preventing crafted payloads with malformed interior entries from causing OOB reads or crashes (#7502)- Fixed
DenseSet::SetExpiryTimenot settingexpiration_used_, causingRandomPairsUniqueto skip expiry filtering and return already-expired keys (#7392) - Fixed two use-after-free bugs in DenseSet expiry chain walks (
ExpireIfNeededInternal,Find2) where deleting a node leftnode/currdangling for subsequent iterations (#7393) - Fixed single-field hashes incorrectly converting to dense_set encoding when the value exceeded
max_map_field_len; listpack encoding is now preserved for single-field hashes regardless of value size (#7257) - Fixed an out-of-bounds read in
BITCOUNTwithBITindex mode when the end index falls exactly on a byte boundary, and incorrect handling of both-negative inverted ranges on short strings (#7190) - Fixed per-type memory accounting underflow when
AutoUpdater::Run()processed a value whose object type changed (e.g., SORT STORE overwriting a SET with a LIST) (#7142) - Fixed XADD computing an incorrect memory diff when
RecordJournalpreempted and triggered evictions before the stream size update;UpdateStreamSizeis now called beforeRecordJournal(#7235) - Fixed
MEMORY DEFRAGMENTsilently ignoring parse errors for the threshold float argument and proceeding with defaults (#7346) - Fixed MULTI/EXEC ghost connections (addr=0.0.0.0, phase=scheduled) permanently stalling when a socket RST prevented
CancelBlocking()from being reached (#7273) - Fixed a FIN_WAIT_2/CLOSE_WAIT socket leak where connections blocked on BLPOP and similar commands did not observe EOF when the client closed its socket (#7224)
- Fixed a crash during BGSAVE when a lazily-expired hash field caused an empty container mid-snapshot; DFATAL downgraded to ERROR so the entry is safely skipped (#7452)
- Fixed a crash in DEBUG OBJHIST/UNIQ-STRS from lazy expiry triggered in an unexpected fiber context, and a second bug where the wrong DB index was used when deleting the resulting zombie key (#7241)
- Fixed a bad-input parse error in the RESP server parser logging at ERROR level, which allowed malformed/adversarial clients to flood the error log; downgraded to rate-limited WARNING (#7352)
Zombie Key / Empty Container Cleanup — Fixed a widespread class of bugs where lazy field or member expiry left empty containers as zombie keys, causing DFATAL crashes in subsequent SAVE or incorrect command behavior:
- Empty hash not deleted after: FIELDTTL (#7137), FIELDEXPIRE (#7158), HTTL/HPTTL (#7159), DEBUG OBJHIST/UNIQ-STRS (#7165)
- Empty set not deleted after: SHRINK compaction (#7160), SORT (#7161), SORT BY pattern (#7162), ZUNIONSTORE (#7163), ZINTERSTORE (#7164)
- Lazy expiry disabled during cluster migration serialization to prevent mid-iteration deletions that caused DFATAL on empty-container saves (#7167)
What's Changed
- chore(deps): bump github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs from 1.58.1 to 1.65.0 in /contrib/charts/dragonfly by @dependabot[bot] in #7088
- chore(deps): bump actions/download-artifact from 7 to 8 in the actions group by @dependabot[bot] in #7132
- chore(deps): bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.77.5 to 1.88.5 in /contrib/charts/dragonfly by @dependabot[bot] in #7089
- chore(deps): bump github.com/aws/aws-sdk-go-v2/service/s3 from 1.88.2 to 1.97.3 in /contrib/charts/dragonfly by @dependabot[bot] in #7090
- fix: empty name doc for search by @BorysTheDev in #7127
- chore(helm-chart): update to v1.38.0 by @romange in #7135
- fix: memory calculation after GC by @BorysTheDev in #7136
- fix: sign helm chart PR commits via GitHub API by @vyavdoshenko in #7141
- feat(conn): add pipeline backpressure for IoLoopV2 by @glevkovich in #7018
- fix(server): Use BucketSet directly in OnChange by @dranikpg in #7095
- fix: support LEGACY_GLOG=OFF by @romange in #7139
- fix: delete empty hash after field expiry in FIELDTTL by @vyavdoshenko in #7137
- fix: correct per-type memory accounting when object type changes in AutoUpdater by @romange in #7142
- feat(facade): add connection migration support for IO loop V2 by @glevkovich in #7143
- feat(server): Serializer bucket states by @dranikpg in #7027
- feat(search): add BM25STD scoring engine with per-field TF tracking by @vyavdoshenko in #7101
- feat(server): complete AzureSnapshotStorage implementation by @romange in #7131
- feat(bloom): Implement SCANDUMP cmd for SBF by @abhijat in #7092
- feat: deffer HNSW index updates during restoration by @BorysTheDev in #7126
- chore: split debug info and improve build time on 10% by @BorysTheDev in #7148
- fix: race condition during flush slots by @BorysTheDev in #7145
- fix: delete empty hash after FIELDEXPIRE lazy expiry by @vyavdoshenko in #7158
- fix: delete empty hash after HTTL/HPTTL lazy expiry by @vyavdoshenko in #7159
- fix(v2): set READ_SOCKET phase and refresh heartbeat for timeouts by @glevkovich in #7155
- ci: Use Azure mirror for cgroup test to fix apt failures by @glevkovich in #7172
- fix: delete empty container after SHRINK compaction by @vyavdoshenko in #7160
- fix: SHRINK command memory accounting causes DCHECK crash by @vyavdoshenko in #7173
- refactor: remove duplication logic for HNSW doc deffer processing by @BorysTheDev in #7157
- fix: call flushSlots under transaction to avoid race condition by @BorysTheDev in #7168
- fix: SHRINK build break from obj_type out of scope after merge by @vyavdoshenko in #7177
- fix: clean up empty set after SORT lazy expiry by @vyavdoshenko in #7161
- fix: clean up empty set after SORT BY pattern lazy expiry by @vyavdoshenko in #7162
- fix: disable lazy expiry during migration serialization by @vyavdoshenko in #7167
- fix: clean up empty set after ZUNIONSTORE lazy expiry by @vyavdoshenko in #7163
- fix: clean up empty set after ZINTERSTORE lazy expiry by @vyavdoshenko in #7164
- fix: clean up empty containers after DEBUG OBJHIST/UNIQ-STRS by @vyavdoshenko in #7165
- feat: add replication info to
/metricsendpoint by @EricHayter in #7069 - fix: delete empty hash after FT.SEARCH lazy field expiry by @vyavdoshenko in #7166
- fix(server): Reduce mutex scope in snapshot/streamer by @dranikpg in #7150
- test: Adjust connection tests for V2 architectural differences by @glevkovich in #7156
- refactor: move ExecutionState out of ProtocolClient by @kostasrim in #7170
- chore: add info acl subcommand and metrics by @kostasrim in #7149
- chore(facade): rename predicates, add IoBuf& params, non-functional improvements by @romange in #7012
- feat(search): add WITHSCORES, SCORER, ADDSCORES command support for FT.SEARCH/FT.AGGREGATE by @vyavdoshenko in #7181
- docs(transaction.md): Fix Multiple Typos by @RoyTouw77 in #7194
- fix: OOB in BITCOUNT and some refactoring by @BorysTheDev in #7190
- chore: add logs to detect OOM during replication restart process by @BorysTheDev in #7197
- chore(server): Introduce read budget to prep for tagged chunk loading by @abhijat in #7109
- feat: add Apply method to CmdArgParser by @BorysTheDev in #7204
- fix(server): reject negative numkeys in EVAL/EVALSHA to avoid CHECK abort by @vyavdoshenko in #7203
- feat(search): add TFIDF and TFIDF.DOCNORM scorers by @vyavdoshenko in #7200
- feat(bloom): Implement LOADCHUNK cmd for SBF by @abhijat in #7169
- fix(server): Re-use journal executor by @dranikpg in #7201
- fix(server): Process empty buckets in snapshot by @dranikpg in #7185
- chore(deps): bump github.com/moby/spdystream from 0.5.0 to 0.5.1 in /contrib/charts/dragonfly by @dependabot[bot] in #7175
- chore(server): Extended SerializerBase test by @dranikpg in #7179
- test: add logging to bullmq tests by @vyavdoshenko in #7209
- chore(deps): bump github.com/jackc/pgx/v5 from 5.7.6 to 5.9.2 in /contrib/charts/dragonfly by @dependabot[bot] in #7207
- feat: add memory consumption for HNSW by @BorysTheDev in #7205
- fix(server): Don't use item queue for inlined load by @dranikpg in #7211
- fix: replication for data loaded by DFLY LOAD command by @BorysTheDev in #6740
- build(deps): bump filippo.io/edwards25519 from 1.1.0 to 1.1.1 in /contrib/charts/dragonfly by @dependabot[bot] in #6678
- tests: Update pytest by @abhijat in #7212
- feat: new methods in CmdArgParser by @BorysTheDev in #7208
- feat: add stricter cluster config validation by @BorysTheDev in #7210
- feat: DEBUG TRAFFIC per-listener recording and memcache replay by @vyavdoshenko in #7192
- feat: DEBUG TRAFFIC REPLICA - record replication stream on replicas by @vyavdoshenko in #7217
- feat(core): Add ShardedHashMap — sharded concurrent hash map by @mkaruza in #7196
- fix: avoid O(n) scans in NotifyWatchQueue by @kostasrim in #7225
- test(connection): add a fix for FIN_WAIT_2 leak bug with BLPOP by @romange in #7224
- tests: Wait for monitor set up before firing commands by @abhijat in #7226
- fix(search): propagate FLAT VECTOR_RANGE score alias to FT.SEARCH reply by @vyavdoshenko in #7222
- chore(server) server: Add mem buf controller by @abhijat in #7198
- perf(facade): defer V2 ReplyBatch flush to reduce syscalls by @glevkovich in #7213
- test: add more HNSW tests by @BorysTheDev in #7216
- feat(pubsub): Replace RCU-based ChannelStore with ShardedHashMap by @mkaruza in #7174
- refactor: drop extra metadata for HNSW replication by @BorysTheDev in #7215
- build(deps): update meta-memcache requirement from >=2 to >=2.2.0 in /tests/dragonfly by @dependabot[bot] in #7228
- build(deps): update pyyaml requirement from >=6.0 to >=6.0.3 in /tests/dragonfly by @dependabot[bot] in #7231
- build(deps): update pytest-icdiff requirement from >=0.8 to >=0.9 in /tests/dragonfly by @dependabot[bot] in #7230
- build(deps): update packaging requirement from >=23.1 to >=26.2 in /tests/dragonfly by @dependabot[bot] in #7229
- feat: add lacked functionality for OAHSet by @BorysTheDev in #7233
- feat(core): Introduce zero-alloc StreamNodeObj tagged pointer by @mkaruza in #7104
- feat: support ~ optional match operator in query language by @vyavdoshenko in #7227
- feat(s3): make AwsS3SnapshotStorage always available; AWS SDK backend optional by @romange in #7180
- fix: memory track before preemption in OpAdd by @kostasrim in #7235
- feat(server): Implement tagged chunk loading by @abhijat in #7070
- fix: handle incompressible data in HuffmanCheckTask by @shitaoxai in #7251
- tests: Wait for slot flush propagation by @abhijat in #7243
- chore: remove a temporary barrier on replica executor side by @romange in #7214
- feat(tools): add AI-powered release notes generator by @vyavdoshenko in #7252
- fix: defer empty-container cleanup in DEBUG OBJHIST/UNIQ-STRS to shard_queue fiber by @vyavdoshenko in #7241
- fix: single-field hash should use listpack even with large values by @romange in #7257
- feat(tools): add Copilot backend, per-commit cache, and async refactor to release notes generator by @romange in #7264
- fix(tests): Improve shutdown save test by @dranikpg in #7237
- feat(tools): extend release notes generator with announce target by @romange in #7268
- chore: adjust code for LEGACY_GLOG=OFF build by @romange in #7154
- Add memtier-compatible latency JSON to dfly_bench by @romange in #7269
- fix: accept optional
SCHEDULEsubcommand in BGSAVE by @vyavdoshenko in #7286 - ci: skip flaky BullMQ QueueEvents.run() race test by @vyavdoshenko in #7292
- CI: match mastodon tests to upstream by @abhijat in #7307
- chore: pull latest helio by @kostasrim in #7310
- fix(ci): pin helm version to v3.21.0 to match golden files by @vyavdoshenko in #7311
- feat(search): Porter stemming for TEXT fields with NOSTEM, LANGUAGE, LANGUAGE_FIELD by @vyavdoshenko in #7295
- fix(search): guard RebuildForGroup against freed DocIds on lazy key expiry by @vyavdoshenko in #7313
- test(connection): add regression tests for MULTI/EXEC tx-queue stall by @romange in #7273
- feat(tiering): Mutable hash commands by @dranikpg in #6085
- fix(server): use LOG_EVERY_T for OOM error logging by @bitborne in #7220
- fix(server): Reconcile bucket set by @dranikpg in #7260
- fix(ci): install libheif codec plugins for HEIC/AV1 support in Mastodon tests by @vyavdoshenko in #7315
- fix(server): Fix iterator invalidation by @dranikpg in #7316
- chore: fix test shutdown bug by @romange in #7317
- build(deps): bump the actions group across 1 directory with 2 updates by @dependabot[bot] in #7193
- feat(cluster): add flags for coordinator timeouts by @bitborne in #7221
- refactor: store hnsw metadata together with index by @BorysTheDev in #7242
- fix: strip CRLF from Lua error_reply and status_reply by @vyavdoshenko in #7332
- fix(tests): Transient 502 network errors crash test suite due to missing retries in urllib (#7238) by @paarth-k2002 in #7314
- CI: allow arm in repeat-test by @abhijat in #7334
- refactor: add method CompactObject::SetMemberTime by @BorysTheDev in #7335
- fix: slot redirection after takeover corrupted by @kostasrim in #7263
- fix: migration restart flush race by @kostasrim in #7333
- fix(test): Disable cooling for pytest with tiering and cluster by @mkaruza in #7330
- feat(server): Make DbSlice consumer an interface by @dranikpg in #7253
- server: Handle errors in memory cmd parse by @abhijat in #7346
- feat(search): exact phrase queries with slop and BM25 scoring by @vyavdoshenko in #7319
- facade: Downgrade bad input parse failure to warning by @abhijat in #7352
- fix: prevent PII leaks in FailedCommandToString error logs by @vyavdoshenko in #7338
- fix(search): use global stats for shard-independent text scoring by @vyavdoshenko in #7250
- core: split LargeString out of RobjWrapper by @romange in #7361
- feat(server): Journal omits by @dranikpg in #7060
- test: fix flaky cluster migration tiering test by @romange in #7367
- core: replace ROBJ_TAG with per-collection tags, drop RobjWrapper::type_ by @romange in #7364
- fix(lua): Add input size validation to dragonfly.randstr() by @mkaruza in #7368
- fix(lua): Harden sandbox by protecting rawset, setmetatable, and getmetatable by @mkaruza in #7370
- chore: more logs for replication tests by @BorysTheDev in #7353
- fix(lua): Restrict load() to text-only mode by @mkaruza in #7376
- fix(server): Enable journal omits only under flag by @dranikpg in #7371
- chore: release action improvements by @romange in #7256
- fix(search): suppress automove double-use warnings in parser.y by @vyavdoshenko in #7383
- facade: Trim parsed args if capacity much higher than size by @abhijat in #7378
- perf(facade): use CycleClock for ReplyBuilder send timing by @romange in #7388
- perf(server): reduce ProactorBase::GetMonotonicTimeNs callers by @romange in #7387
- fix(dense_set): avoid use-after-free in expiry chain walks by @vyavdoshenko in #7393
- perf(server): use CycleClock for streamer/disk-storage timing by @romange in #7394
- fix(string_map): mark DenseSet expiration_used in SetExpiryTime by @vyavdoshenko in #7392
- Increase test_big_huge_streaming_restart timeout by @dranikpg in #7384
- ci: build with LEGACY_GLOG=OFF by @romange in #7395
- perf(cluster): use CycleClock for incoming migration throttle timing by @romange in #7398
- facade: Fix comment floor size for arg trim by @abhijat in #7402
- Remove SerializedMap, store listpack directly in tiered value by @dranikpg in #7374
- feat: integrate OAHSet by @BorysTheDev in #7246
- fix(server): run RANDOMKEY scan on regular fiber to allow preempt by @vyavdoshenko in #7405
- refactor(test): collapse duplicate tiering migration tests into shared helper by @romange in #7409
- fix(tests): disable omit assert by @dranikpg in #7413
- feat(facade): bound IoLoopV2 dispatch_q_ quota to prevent starvation by @glevkovich in #7234
- feat(aws): pass S3 endpoint directly to AwsCredsProvider by @romange in #7408
- feat(compact_object): extend Huffman encoding up to 16KB with varint header by @romange in #7406
- chore(server): Make listpack bounds configurable by @dranikpg in #7407
- feat(server): Support CLIENT LIST [TYPE ...] [ID ...] filters by @vyavdoshenko in #7377
- chore: do not unwrap parsed expression in tests by @kostasrim in #7380
- feat(facade): add per-protocol IoLoopV2 flags for Memcache and RESP by @glevkovich in #7424
- feat: integrate SIMD into OAHSet by @BorysTheDev in #7306
- fix(test): Remove stale keyspace assertion in _run_tiering_migration by @mkaruza in #7427
- core: zero-copy GET primitives by @romange in #7412
- refactor: ReplicaInfo into class by @BorysTheDev in #7415
- feat(server): Yield fiber periodically during long container iterations by @mkaruza in #7391
- test: add long HNSW tests by @BorysTheDev in #7418
- fix(search): preserve decimal GEO radii by @fallintoplace in #7422
- chore: remove test_tls_when_read_write_is_interleaved by @kostasrim in #7429
- docs: update pub-sub.md to reflect ShardedHashMap architecture by @Copilot in #7239
- chore: factor out boilerplate for tests by @kostasrim in #7419
- test: relax ClientPause GET timing budget for sanitizer builds by @vyavdoshenko in #7445
- fix(search): honor backslash escapes in TEXT tokenization by @vyavdoshenko in #7438
- fix(search): preserve empty TAG/TEXT values in FT.SEARCH RETURN by @vyavdoshenko in #7434
- test(search): wait for initial indexing before FT.SEARCH by @vyavdoshenko in #7444
- chore(server): Transaction inlining comments by @dranikpg in #7441
- docs: rewrite transaction.md to align with current codebase by @romange in #7448
- feat(server): tagged chunk write path by @abhijat in #7416
- chore: dfly version clean ups by @romange in #7442
- perf: zero-copy GET infrastructure (common, core, facade) by @romange in #7433
- fix(rdb): tolerate transiently empty container during snapshot by @vyavdoshenko in #7452
- fix(server): Cancel transactions by @dranikpg in #7399
- fix(ci): correct docker health check condition by @fallintoplace in #7423
- perf(facade): defer pipeline flushes in IoLoopV2 by @glevkovich in #7437
- test(search): wait for indexing before searching populated index by @vyavdoshenko in #7464
- Add cluster design doc by @BorysTheDev in #7435
- feat(search): support w'...' glob wildcards on text and tag fields by @vyavdoshenko in #7456
- ci: parallelize ctest runs with -j$(nproc) by @vyavdoshenko in #7440
- feat(search): implement FT.HYBRID command with LINEAR/RRF score fusion by @vyavdoshenko in #7420
- fix(search): accept phrases and affixes in parenthesized field conditions by @vyavdoshenko in #7455
- refactor(search): factor shared query-grammar atoms into term_atom by @vyavdoshenko in #7467
- chore: disable default settings that cause regression in CI by @romange in #7465
- tests: Fix test_denyoom_commands by removing RSS factor by @abhijat in #7446
- Fix bigvalue cancel by @dranikpg in #7470
- fix: HNSW index building bug on replica by @BorysTheDev in #7453
- perf(facade): batch V2 control-path replies in ProcessControlMessages by @glevkovich in #7479
- readme(readme): add user conference link by @worldsoup in #7483
- fix(search): parse RETURN/LOAD count as tokens, not field-specs by @vyavdoshenko in #7482
- chore(server): Small snapshot updates by @dranikpg in #7480
- fix(json): surface JSON.DEBUG arg parse errors instead of aborting by @vyavdoshenko in #7493
- feat: info replication is lock free by @BorysTheDev in #7348
- ci: run C++ unit tests serially (drop ctest -j) by @vyavdoshenko in #7495
- chore: drop extra drakarys logs by @BorysTheDev in #7490
- feat(search): accept bare identifiers in FT.CREATE schema on JSON by @vyavdoshenko in #7488
- fix: enable rdb_sbf_chunked by default and fix sbf serialization bug by @romange in #7475
- chore: reduce log level for Drakarys by @BorysTheDev in #7497
- docs: add HNSW replication doc by @BorysTheDev in #7219
- fix: deep-validate listpack/intset payloads on RESTORE by @vyavdoshenko in #7502
- fix(server): Propagate error on bigvalue cancel by @dranikpg in #7486
- refactor: drop extra dispatch for info replica section by @BorysTheDev in #7503
- fix(server): Disable single shard batch optimization by @abhijat in #7507
- chore: reproduce inline schedule during save by @kostasrim in #7499
- refactor: add more SIMD into OAHSet by @BorysTheDev in #7478
- feat: improve HSETEX compatibility with Redis by @BorysTheDev in #7510
- CI/build: switch from glog to absl by @abhijat in #7514
- server: Remove redundant ScheduleContext struct by @abhijat in #7516
- fix: slave_repl_offset should be non zero for valkey master by @kostasrim in #7517
- fix: increase timeout for test_randomkey_during_bgsave by @kostasrim in #7519
- test(fuzz): full command coverage and a valid, repaired RESP seed corpus by @vyavdoshenko in #7511
- fix: batched backpressure by @dranikpg in #7515
Huge thanks to all the contributors! ❤️
New Contributors
- @RoyTouw77 made their first contribution in #7194
- @shitaoxai made their first contribution in #7251
- @bitborne made their first contribution in #7220
- @paarth-k2002 made their first contribution in #7314
- @fallintoplace made their first contribution in #7422
Full Changelog: v1.38.0...v1.39.0