valkey_client 2.0.0
valkey_client: ^2.0.0 copied to clipboard
Smart client for Valkey and Redis. Supports Standalone, Sentinel, and Cluster modes.
Changelog #
2.0.0 #
Added #
- Enterprise SSL/TLS Support: Implemented full support for encrypted connections (
SecureSocket) across Standalone, Pool, and Cluster clients.- Configuration: Added
useSsl,sslContext, andonBadCertificateoptions toValkeyConnectionSettings. - Cloud Ready: Fully compatible with managed services requiring TLS (AWS ElastiCache, Azure Cache for Redis, GCP Memorystore).
- Dev Friendly: Supports self-signed certificates via the
onBadCertificatecallback for local development.
- Configuration: Added
1.8.0 #
Added #
- Automatic Cluster Failover: Implemented topology refresh and retry logic on connection failures. The client now automatically detects dead nodes, updates the cluster map, and redirects commands to the new master node, ensuring high availability during server outages.
1.7.0 #
Added #
- Connection Pool Hardening (Smart Release):
ValkeyPoolnow automatically detects and discards "dirty" connections (e.g., inside a Transaction or Pub/Sub mode) or closed connections upon release. This prevents pool pollution and ensures that acquired connections are always clean and ready for use. - Enhanced Developer Experience: Expanded
Redisaliases inredis_client.dart. Added aliases for Exceptions (RedisException,RedisConnectionException, etc.), Configuration (RedisConnectionSettings), and Data Models (RedisMessage), allowing for a seamless migration from other Redis clients. - Robust Resource Management: Implemented strict ownership tracking within
ValkeyPoolto prevent resource leaks and ensure thread safety.release()anddiscard()are now idempotent and safe to call multiple times. - Client Introspection:
ValkeyClientnow exposesisStatefulandisConnectedproperties, which support the new smart pooling logic and allow for custom connection management.
1.6.0 #
Added #
- Sharded Pub/Sub Support: Implemented
SPUBLISH,SSUBSCRIBE, andSUNSUBSCRIBE.- Enables high-performance messaging in Cluster mode by routing messages only to specific shards instead of broadcasting to all nodes.
- Fully compatible with Redis 7.0+ and Valkey 9.0+.
- Atomic Counters: Added
INCR,DECR,INCRBY, andDECRBYcommands for atomic integer operations. - Connection Helper: Added
ECHOcommand support. - Subscription Enhancements: The
Subscriptionobject now has an.unsubscribe()method, allowing easier lifecycle management directly from the subscription instance.
Changed #
- Internal Parser: Updated the RESP parser to handle
smessage,ssubscribe, andsunsubscribepush message types.
1.5.0 #
Added #
- High Availability & Resilience: Implemented transparent handling for Cluster Redirections (
-MOVEDand-ASK).- The client now automatically retries commands on the correct node when a slot migration or failover occurs.
-MOVEDHandling: Automatically updates the internalClusterSlotMapand redirects the request to the new master.-ASKHandling: Successfully handles temporary slot migrations by sendingASKINGcommands to the target node.
- Developer Experience: Added
RedisClientalias. You can now useRedisClientinterchangeably withValkeyClientfor a familiar development experience. - Configuration: Added
maxRedirectsparameter toValkeyClusterClient(default:5) to control the maximum number of retries before throwing an exception. - Inspection Helper: Added
getMasterFor(key)method to retrieve theClusterNodeInfocurrently responsible for a specific key. This is useful for debugging topology changes.
Changed #
- Robustness:
ValkeyClusterClientno longer fails immediately upon encountering topology changes but attempts to recover using the new redirection logic.
1.4.0 #
Added #
- Multi-key Command Support (MGET): Implemented
mgetsupport forValkeyClusterClient.- Core Update: Updated
ValkeyClusterClientto handle multi-key operations gracefully. - Strategy: Uses a Scatter-Gather strategy to group keys by node.
- Performance: Utilizes Pipelining (sending multiple
GETcommands concurrently) instead of a singleMGETto avoidCROSSSLOTerrors while maintaining high performance. - Ordering: Correctly re-assembles results in the requested order.
- Core Update: Updated
Fixed #
- Logging: Removed the unintended forced logging (
INFOlevel) during cluster NAT detection. The client now correctly respects the user's globally configured log level.
1.3.0 #
Added #
- Cluster Client (v1.3.0): Introduced the new
ValkeyClusterClientfor automatic command routing in cluster mode.- This cluster-aware client fetches the topology using
clusterSlots()during theconnect()call. - Automatically detects NAT/Docker environments by comparing the initial connection IPs with
CLUSTER SLOTSresponse, enabling correct routing without manual configuration. - Fetches topology using
clusterSlots()onconnect(). - Manages internal
ValkeyPools for each discovered master node. - Automatically routes single-key commands (
GET,SET,HSET, etc.) to the correct node using thegetHashSlotcalculator.
- This cluster-aware client fetches the topology using
ValkeyCommandsBase: Created a new base interface (lib/valkey_commands_base.dart) to abstract common data commands, preventing code duplication betweenValkeyClientBaseandValkeyClusterClientBase.- Internal (Hash Slot): Added a dependency-free hash slot calculator (
lib/src/cluster_hash.dart) implementing CRC-16/XMODEM. - Internal (Slot Map): Added
ClusterSlotMap(lib/src/cluster_slot_map.dart) to manage the mapping of slots to nodes efficiently. - Example (Cluster): Added
example/cluster_client_example.dartto demonstrateValkeyClusterClientusage and its auto-NAT routing. - Testing (Cluster):
- Added
test/cluster_hash_test.dartfor validating the CRC-16 hash slot calculator. - Added
test/valkey_cluster_client_test.dartfor integration testing of the new cluster client.
- Added
Fixed #
- Critical
ValkeyClientHang (IPv6): Fixed a bug inValkeyClient.connectwhere connecting to127.0.0.1on macOS/Windows could hang indefinitely by attempting an IPv6 connection (::1) first. The client now forcesInternetAddress.loopbackIPv4for loopback addresses. - Critical
ValkeyClusterClientRouting Bug: Fixed a bug where the client's NAT auto-detection logic (_hostMap) was not being used consistently, causing connection pools to be created with incorrect (internal) IPs.
Known Limitations #
MGET: Themgetcommand (defined inValkeyCommandsBase) is not implemented inValkeyClusterClientin this version and will throw anUnimplementedError. Multi-key scatter-gather operations are planned for v1.4.0.Transactions&Pub/Sub: Cluster-aware Transactions (which require multi-node coordination) and Sharded Pub/Sub (SSUBSCRIBE,SPUBLISH) are not implemented in this version. Sharded Pub/Sub is planned for v1.6.0 as part of the v2.0.0 cluster roadmap.
1.2.0 #
Added #
- Cluster Auto-Discovery (Foundation): Implemented the
client.clusterSlots()command. This is the first step towards full cluster support (v2.0.0), allowing the client to fetch the cluster's slot topology. - New Cluster Models: Added
ClusterNodeInfoandClusterSlotRange(inlib/src/cluster_info.dart) to represent the parsed slot map returned by the server. - Internal (Parser): Added a new, testable, top-level function
parseClusterSlotsResponse(inlib/src/cluster_slots_parser.dart) to handle the complexCLUSTER SLOTSarray response, respecting theavoid_classes_with_only_static_memberslint rule.
Fixed #
- Critical Hang Bug (Command Timeout): Fixed a critical bug where the client would hang indefinitely if the server did not send a response (e.g., a standalone server receiving the
CLUSTER SLOTScommand). commandTimeoutImplementation:- Added a
commandTimeout(default 10s) property toValkeyConnectionSettingsand theValkeyClientconstructor. ValkeyPoolnow correctly propagates this setting to newly created clients.- The core
executemethod now applies this timeout to all standard commands, throwing aValkeyClientExceptionon timeout.
- Added a
- Queue Desync Prevention: The
onTimeouthandler now correctly removes the staleCompleterfrom the_responseQueue, preventing potential desynchronization issues on late responses.
Documentation #
- New Example: Added
example/cluster_auto_discovery_example.dartto demonstrate the usage of the newclusterSlots()command and its correct timeout behavior when run against a standalone (non-cluster) server.
1.1.0 #
Added #
- Built-in Connection Pooling: Implemented
ValkeyPoolfor efficient, high-concurrency connection management.- Includes
pool.acquire()andpool.release()methods. - Automatically handles connection creation up to
maxConnections. - Implemented a wait queue for requests when the pool is full.
- Added health checks (
PING) onacquireto discard unhealthy connections.
- Includes
ValkeyConnectionSettings: Added a class to hold connection parameters for the pool.
Fixed #
- Fixed a bug in the pool's
release()logic where unhealthy (closed) clients were incorrectly returned to the pool, causing errors on reuse.
1.0.0 #
π First Production-Ready Stable Release (Standalone/Sentinel) π
This release marks the first stable version of valkey_client suitable for production use in Standalone and Sentinel environments. All core data types, transactions, and Pub/Sub features are implemented and tested.
Changed #
- Production-Ready Cleanup: Removed all internal debug
printstatements. - Error Handling: Replaced standard
Exceptionswith specific exception classes (ValkeyConnectionException,ValkeyServerException,ValkeyClientException,ValkeyParsingException) for robust error handling. - Logging: Added an internal lightweight logger (via
ValkeyClient.setLogLevel(ValkeyLogLevel)) instead of requiringpackage:logging. (Logging isOFFby default).
Fixed #
- Test Suite: Corrected several tests (e.g.,
WRONGTYPE,EXECABORT) to correctly expect the new specific exception types (ValkeyServerException). - Lints: Addressed
constant_identifier_nameslint forValkeyLogLevelviaanalysis_options.yaml.
Documentation #
- README.md: Updated to reflect
v1.0.0status. Added an Important Note regarding the lack of built-in connection pooling and recommendingpackage:pool. - API Reference: Added comprehensive Dart Doc comments for all public classes and methods in
valkey_client_base.dartandexceptions.dart.
0.12.0 #
Added #
- New Commands (Pub/Sub Introspection): Added commands to inspect the Pub/Sub system state. These commands do not require the client to be in Pub/Sub mode.
client.pubsubChannels([pattern]): Lists active channels.client.pubsubNumSub(channels): Returns aMapof channels and their subscriber counts.client.pubsubNumPat(): Returns the total number of pattern subscriptions.
0.11.0 #
Added #
- Transactions: Implemented basic transaction support.
client.multi(): Marks the start of a transaction block.client.exec(): Executes all queued commands and returns their replies as aList<dynamic>?.client.discard(): Flushes all commands queued in a transaction.
- Client State: The client now tracks transaction state (
_isInTransaction). Most commands sent during this state will return+QUEUED(which the client now handles).
0.10.0 #
Added #
- Advanced Pub/Sub: Completed the core Pub/Sub feature set.
client.unsubscribe(): Unsubscribes from specific channels or all channels.client.psubscribe(): Subscribes to patterns, returning aSubscriptionobject.client.punsubscribe(): Unsubscribes from specific patterns or all patterns.
pmessageHandling: The client now correctly parses and emitspmessage(pattern message) events via theValkeyMessagestream (withpatternfield populated).- State Management: Improved internal state management (
_isInPubSubMode,_resetPubSubState) for handling mixed and multiple subscription/unsubscription scenarios.
Fixed #
- Critical Pub/Sub Hang: Fixed a complex bug where
await unsubscribe()orawait punsubscribe()would hang (timeout).- Root Cause:
SUBSCRIBEandPSUBSCRIBEcommands were incorrectly leaving their commandCompleters in the_responseQueue. - Symptom: This caused the queue to become desynchronized, and subsequent
unsubscribe/punsubscribecalls would process the staleCompleterinstead of their own, leading to an infinite wait.
- Root Cause:
- Logic Refactor: The
executemethod is now corrected to not addCompleters to the_responseQueuefor any Pub/Sub management commands (SUBSCRIBE,PSUBSCRIBE,UNSUBSCRIBE,PUNSUBSCRIBE), as their futures are managed separately (e.g.,Subscription.readyor theFuture<void>returned byunsubscribe).
0.9.1 #
Note: This is the first version published to pub.flutter-io.cn with basic Pub/Sub support. Version 0.9.0 was unpublished due to bugs.
Fixed #
- Critical Pub/Sub Bug: Fixed the issue where the client would stop receiving Pub/Sub messages after the initial subscription confirmation, causing tests to time out. The root cause involved the handling of the
SUBSCRIBEcommand'sCompleterinterfering with theStreamSubscription. - Parser Logic: Improved the internal parser logic (
_processBuffer) to more reliably distinguish between Pub/Sub push messages and regular command responses, especially while in the subscribed state. - Test Logic: Corrected the authentication failure test (
should throw an Exception when providing auth...) to expect the actual error message returned by the server (ERR AUTH...) instead of a custom one.
Changed #
- Pub/Sub Example: Updated the Pub/Sub example (
example/valkey_client_example.dart) to reflect the correct usage with the newSubscriptionobject (includingawait sub.ready).
0.9.0 #
Note: This version was not published to pub.flutter-io.cn due to unresolved issues in the Pub/Sub implementation found during testing.
Added #
- New Commands (Pub/Sub): Added basic Publish/Subscribe functionality.
client.publish(): Posts a message to a channel.client.subscribe(): Subscribes to channels and returns aStream<ValkeyMessage>for receiving messages.
- Push Message Handling: The internal parser and client logic were updated to handle asynchronous push messages (like pub/sub messages) separate from command responses.
ValkeyMessageClass: Introduced a class to represent incoming pub/sub messages.
Known Limitations #
- Once subscribed, only
UNSUBSCRIBE,PUNSUBSCRIBE,PING, andQUITcommands are allowed by Redis/Valkey. The client currently enforces this restriction partially. Fullunsubscribelogic is not yet implemented. - Pattern subscription (
PSUBSCRIBE,PUNSUBSCRIBE) is not yet supported.
0.8.0 #
Added #
- New Commands (Key Management): Added commands for managing keys.
client.del()client.exists()client.expire()(set timeout in seconds)client.ttl()(get remaining time to live)
- These commands primarily return
Integerresponses.
0.7.0 #
Added #
- New Commands (Sets): Added commands for working with Sets.
client.sadd()/client.srem()client.smembers()
- New Commands (Sorted Sets): Added commands for working with Sorted Sets (leaderboards).
client.zadd()/client.zrem()client.zrange()(by index)
- These commands utilize the existing
Integer,Array, andBulk Stringparsers.
0.6.0 #
Added #
- New Commands (Lists): Added commands for working with Lists.
client.lpush()/client.rpush()client.lpop()/client.rpop()client.lrange()
- These commands utilize the existing
Integer,Bulk String, andArrayparsers.
0.5.0 #
Added #
- New Commands (Hashes): Added
client.hset(),client.hget(), andclient.hgetall(). - Upgraded RESP Parser: The internal parser now supports Integers (
:). hsetreturns anint(1for new field,0for update).hgetallconveniently returns aMap<String, String>.
Fixed #
- Critical Auth Bug: Fixed a bug where
connect()would time out (hang) if authentication failed (e.g., providing a password to a no-auth server). - Test Stability (
FLUSHDB): Fixed flaky command tests (likeHSETreturning0instead of1) by addingFLUSHDBtosetUpAll, ensuring a clean database for each test run. - Test Logic: Fixed the authentication failure test to expect the actual server error message (e.g.,
ERR AUTH) instead of a custom one.
Changed #
- Test Suite: Refactored the entire test setup (
valkey_client_test.dart) to use acheckServerStatus()helper. This reliably checks server availability before defining tests, preventing false skips and cleaning up the test logic.
0.4.0 #
Added #
- Upgraded RESP Parser: Implemented a full recursive parser.
- The parser now supports Arrays (
*), completing the core RESP implementation.
- The parser now supports Arrays (
- New Command: Added
client.mget()(Multiple GET) which relies on the new array parser. - Internal: Refactored the parser logic into a
_BufferReaderfor cleaner, more robust parsing.
0.3.0 #
Added #
- New Commands: Added
client.set()andclient.get()methods. - Upgraded RESP Parser: The internal parser now supports Bulk Strings (
$). - This enables handling standard string values (e.g.,
GET mykey) andnullreplies (e.g.,GET non_existent_key).
0.2.0 #
Added #
- Command Execution Pipeline: Implemented the core
executemethod to send commands and process responses via a queue. - PING Command: Added the first user-facing command:
client.ping(). - Basic RESP Parser: Added an internal parser to handle simple string (
+) and error (-) responses, preparing for full RESP3 support.
0.1.0 #
This is the first functional release, implementing the core connection logic.
Added #
- Core Connection: Implemented the initial client connection logic.
connect(): Connects to the Valkey server.close(): Closes the connection.onConnected: AFuturethat completes when the connection is established.
- Documentation:
- Added public API documentation (
lib/valkey_client.dart). - Added a comprehensive usage example (
example/valkey_client_example.dart).
- Added public API documentation (
- Testing:
- Added unit tests for connection, connection failure, and disconnection scenarios.
0.0.1 #
- Initial version. (Placeholder)