From 220d060dff63050570d53101873d0764ffc83195 Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Mon, 8 Dec 2025 15:30:04 +0000 Subject: [PATCH] different A:A approach - use a multiplexer that spans multiple sub muxers --- .../ConfigurationOptions.cs | 32 +- .../ConnectionMultiplexer.cs | 4 +- .../MultiGroupDatabase.Async.cs | 66 +++ .../MultiGroupDatabase.Geo.Async.cs | 52 +++ .../MultiGroupDatabase.Geo.cs | 50 ++ .../MultiGroupDatabase.Hashes.Async.cs | 128 ++++++ .../MultiGroupDatabase.Hashes.cs | 130 ++++++ .../MultiGroupDatabase.HyperLogLog.Async.cs | 25 + .../MultiGroupDatabase.HyperLogLog.cs | 23 + .../MultiGroupDatabase.Keys.Async.cs | 80 ++++ .../MultiGroupDatabase.Keys.cs | 79 ++++ .../MultiGroupDatabase.Lists.Async.cs | 79 ++++ .../MultiGroupDatabase.Lists.cs | 77 ++++ .../MultiGroupDatabase.Sets.Async.cs | 64 +++ .../MultiGroupDatabase.Sets.cs | 65 +++ .../MultiGroupDatabase.SortedSets.Async.cs | 124 +++++ .../MultiGroupDatabase.SortedSets.cs | 127 +++++ .../MultiGroupDatabase.Streams.Async.cs | 122 +++++ .../MultiGroupDatabase.Streams.cs | 121 +++++ .../MultiGroupDatabase.Strings.Async.cs | 119 +++++ .../MultiGroupDatabase.Strings.cs | 118 +++++ .../MultiGroupDatabase.VectorSets.Async.cs | 49 ++ .../MultiGroupDatabase.VectorSets.cs | 47 ++ src/StackExchange.Redis/MultiGroupDatabase.cs | 105 +++++ .../MultiGroupMultiplexer.cs | 432 ++++++++++++++++++ .../PublicAPI/PublicAPI.Unshipped.txt | 4 +- .../StackExchange.Redis.csproj | 6 + 27 files changed, 2322 insertions(+), 6 deletions(-) create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Async.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Geo.Async.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Geo.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Hashes.Async.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Hashes.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.HyperLogLog.Async.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.HyperLogLog.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Keys.Async.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Keys.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Lists.Async.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Lists.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Sets.Async.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Sets.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.SortedSets.Async.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.SortedSets.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Streams.Async.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Streams.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Strings.Async.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.Strings.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.VectorSets.Async.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.VectorSets.cs create mode 100644 src/StackExchange.Redis/MultiGroupDatabase.cs create mode 100644 src/StackExchange.Redis/MultiGroupMultiplexer.cs diff --git a/src/StackExchange.Redis/ConfigurationOptions.cs b/src/StackExchange.Redis/ConfigurationOptions.cs index c0021f024..d10221968 100644 --- a/src/StackExchange.Redis/ConfigurationOptions.cs +++ b/src/StackExchange.Redis/ConfigurationOptions.cs @@ -40,6 +40,12 @@ public static int ParseInt32(string key, string value, int minValue = int.MinVal return tmp; } + public static float ParseSingle(string key, string value) + { + if (!Format.TryParseDouble(value, out double tmp)) throw new ArgumentOutOfRangeException(key, $"Keyword '{key}' requires a numeric value; the value '{value}' is not recognised."); + return (float)tmp; + } + internal static bool ParseBoolean(string key, string value) { if (!Format.TryParseBoolean(value, out bool tmp)) throw new ArgumentOutOfRangeException(key, $"Keyword '{key}' requires a boolean value; the value '{value}' is not recognised."); @@ -111,7 +117,8 @@ internal const string Tunnel = "tunnel", SetClientLibrary = "setlib", Protocol = "protocol", - HighIntegrity = "highIntegrity"; + HighIntegrity = "highIntegrity", + Weight = "weight"; private static readonly Dictionary normalizedOptions = new[] { @@ -143,6 +150,7 @@ internal const string CheckCertificateRevocation, Protocol, HighIntegrity, + Weight, }.ToDictionary(x => x, StringComparer.OrdinalIgnoreCase); public static string TryNormalize(string value) @@ -843,6 +851,7 @@ public static ConfigurationOptions Parse(string configuration, bool ignoreUnknow heartbeatInterval = heartbeatInterval, heartbeatConsistencyChecks = heartbeatConsistencyChecks, highIntegrity = highIntegrity, + Weight = Weight, }; /// @@ -925,6 +934,11 @@ public string ToString(bool includePassword) Append(sb, OptionKeys.SetClientLibrary, setClientLibrary); Append(sb, OptionKeys.HighIntegrity, highIntegrity); Append(sb, OptionKeys.Protocol, FormatProtocol(Protocol)); + var weight = Weight; + if (!float.IsNaN(weight)) + { + Append(sb, OptionKeys.Weight, weight); + } if (Tunnel is { IsInbuilt: true } tunnel) { Append(sb, OptionKeys.Tunnel, tunnel.ToString()); @@ -940,9 +954,9 @@ public string ToString(bool includePassword) }; } - private static void Append(StringBuilder sb, object value) + private static void Append(StringBuilder sb, object? value) { - if (value == null) return; + if (value is null) return; string s = Format.ToString(value); if (!string.IsNullOrWhiteSpace(s)) { @@ -953,7 +967,8 @@ private static void Append(StringBuilder sb, object value) private static void Append(StringBuilder sb, string prefix, object? value) { - string? s = value?.ToString(); + if (value is null) return; + string? s = value.ToString(); if (!string.IsNullOrWhiteSpace(s)) { if (sb.Length != 0) sb.Append(','); @@ -980,6 +995,7 @@ private void Clear() ChannelPrefix = default; SocketManager = null; Tunnel = null; + Weight = float.NaN; } object ICloneable.Clone() => Clone(); @@ -1091,6 +1107,9 @@ private ConfigurationOptions DoParse(string configuration, bool ignoreUnknown) case OptionKeys.HighIntegrity: HighIntegrity = OptionKeys.ParseBoolean(key, value); break; + case OptionKeys.Weight: + Weight = OptionKeys.ParseSingle(key, value); + break; case OptionKeys.Tunnel: if (value.IsNullOrWhiteSpace()) { @@ -1167,6 +1186,11 @@ private ConfigurationOptions DoParse(string configuration, bool ignoreUnknown) /// public RedisProtocol? Protocol { get; set; } + /// + /// Specify the preference of this connection group relative to others. + /// + public float Weight { get; set; } = float.NaN; + internal bool TryResp3() { // note: deliberately leaving the IsAvailable duplicated to use short-circuit diff --git a/src/StackExchange.Redis/ConnectionMultiplexer.cs b/src/StackExchange.Redis/ConnectionMultiplexer.cs index cc766338a..34aaf7037 100644 --- a/src/StackExchange.Redis/ConnectionMultiplexer.cs +++ b/src/StackExchange.Redis/ConnectionMultiplexer.cs @@ -1128,7 +1128,7 @@ public IDatabase GetDatabase(int db = -1, object? asyncState = null) } // DB zero is stored separately, since 0-only is a massively common use-case - private const int MaxCachedDatabaseInstance = 16; // 17 items - [0,16] + internal const int MaxCachedDatabaseInstance = 16; // 17 items - [0,16] // Side note: "databases 16" is the default in redis.conf; happy to store one extra to get nice alignment etc private IDatabase? dbCacheZero; private IDatabase[]? dbCacheLow; @@ -1281,6 +1281,8 @@ public long OperationCount } } + internal int LatencyTicks { get; private set; } + /// /// Reconfigure the current connections based on the existing configuration. /// diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Async.cs b/src/StackExchange.Redis/MultiGroupDatabase.Async.cs new file mode 100644 index 000000000..6f63e6405 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Async.cs @@ -0,0 +1,66 @@ +using System; +using System.Net; +using System.Threading.Tasks; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // Async methods - Core operations + public Task DebugObjectAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().DebugObjectAsync(key, flags); + + public Task IdentifyEndpointAsync(RedisKey key = default, CommandFlags flags = CommandFlags.None) + => GetDatabase().IdentifyEndpointAsync(key, flags); + + public Task KeyMigrateAsync(RedisKey key, EndPoint toServer, int toDatabase = 0, int timeoutMilliseconds = 0, MigrateOptions migrateOptions = MigrateOptions.None, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyMigrateAsync(key, toServer, toDatabase, timeoutMilliseconds, migrateOptions, flags); + + public Task PingAsync(CommandFlags flags = CommandFlags.None) + => GetDatabase().PingAsync(flags); + + public Task PublishAsync(RedisChannel channel, RedisValue message, CommandFlags flags = CommandFlags.None) + => GetDatabase().PublishAsync(channel, message, flags); + + public Task ExecuteAsync(string command, params object[] args) + => GetDatabase().ExecuteAsync(command, args); + + public Task ExecuteAsync(string command, System.Collections.Generic.ICollection? args, CommandFlags flags = CommandFlags.None) + => GetDatabase().ExecuteAsync(command, args, flags); + + public Task ScriptEvaluateAsync(string script, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().ScriptEvaluateAsync(script, keys, values, flags); + + public Task ScriptEvaluateAsync(byte[] hash, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().ScriptEvaluateAsync(hash, keys, values, flags); + + public Task ScriptEvaluateAsync(LuaScript script, object? parameters = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().ScriptEvaluateAsync(script, parameters, flags); + + public Task ScriptEvaluateAsync(LoadedLuaScript script, object? parameters = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().ScriptEvaluateAsync(script, parameters, flags); + + public Task ScriptEvaluateReadOnlyAsync(string script, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().ScriptEvaluateReadOnlyAsync(script, keys, values, flags); + + public Task ScriptEvaluateReadOnlyAsync(byte[] hash, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().ScriptEvaluateReadOnlyAsync(hash, keys, values, flags); + + public Task LockExtendAsync(RedisKey key, RedisValue value, TimeSpan expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().LockExtendAsync(key, value, expiry, flags); + + public Task LockQueryAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().LockQueryAsync(key, flags); + + public Task LockReleaseAsync(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().LockReleaseAsync(key, value, flags); + + public Task LockTakeAsync(RedisKey key, RedisValue value, TimeSpan expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().LockTakeAsync(key, value, expiry, flags); + + public Task SortAsync(RedisKey key, long skip = 0, long take = -1, Order order = Order.Ascending, SortType sortType = SortType.Numeric, RedisValue by = default, RedisValue[]? get = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortAsync(key, skip, take, order, sortType, by, get, flags); + + public Task SortAndStoreAsync(RedisKey destination, RedisKey key, long skip = 0, long take = -1, Order order = Order.Ascending, SortType sortType = SortType.Numeric, RedisValue by = default, RedisValue[]? get = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortAndStoreAsync(destination, key, skip, take, order, sortType, by, get, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Geo.Async.cs b/src/StackExchange.Redis/MultiGroupDatabase.Geo.Async.cs new file mode 100644 index 000000000..a37283e20 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Geo.Async.cs @@ -0,0 +1,52 @@ +using System.Threading.Tasks; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // Geo Async + public Task GeoAddAsync(RedisKey key, double longitude, double latitude, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoAddAsync(key, longitude, latitude, member, flags); + + public Task GeoAddAsync(RedisKey key, GeoEntry value, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoAddAsync(key, value, flags); + + public Task GeoAddAsync(RedisKey key, GeoEntry[] values, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoAddAsync(key, values, flags); + + public Task GeoRemoveAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoRemoveAsync(key, member, flags); + + public Task GeoDistanceAsync(RedisKey key, RedisValue member1, RedisValue member2, GeoUnit unit = GeoUnit.Meters, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoDistanceAsync(key, member1, member2, unit, flags); + + public Task GeoHashAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoHashAsync(key, members, flags); + + public Task GeoHashAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoHashAsync(key, member, flags); + + public Task GeoPositionAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoPositionAsync(key, members, flags); + + public Task GeoPositionAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoPositionAsync(key, member, flags); + + public Task GeoRadiusAsync(RedisKey key, RedisValue member, double radius, GeoUnit unit = GeoUnit.Meters, int count = -1, Order? order = null, GeoRadiusOptions options = GeoRadiusOptions.Default, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoRadiusAsync(key, member, radius, unit, count, order, options, flags); + + public Task GeoRadiusAsync(RedisKey key, double longitude, double latitude, double radius, GeoUnit unit = GeoUnit.Meters, int count = -1, Order? order = null, GeoRadiusOptions options = GeoRadiusOptions.Default, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoRadiusAsync(key, longitude, latitude, radius, unit, count, order, options, flags); + + public Task GeoSearchAsync(RedisKey key, RedisValue member, GeoSearchShape shape, int count = -1, bool demandClosest = true, Order? order = null, GeoRadiusOptions options = GeoRadiusOptions.Default, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoSearchAsync(key, member, shape, count, demandClosest, order, options, flags); + + public Task GeoSearchAsync(RedisKey key, double longitude, double latitude, GeoSearchShape shape, int count = -1, bool demandClosest = true, Order? order = null, GeoRadiusOptions options = GeoRadiusOptions.Default, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoSearchAsync(key, longitude, latitude, shape, count, demandClosest, order, options, flags); + + public Task GeoSearchAndStoreAsync(RedisKey sourceKey, RedisKey destinationKey, RedisValue member, GeoSearchShape shape, int count = -1, bool demandClosest = true, Order? order = null, bool storeDistances = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoSearchAndStoreAsync(sourceKey, destinationKey, member, shape, count, demandClosest, order, storeDistances, flags); + + public Task GeoSearchAndStoreAsync(RedisKey sourceKey, RedisKey destinationKey, double longitude, double latitude, GeoSearchShape shape, int count = -1, bool demandClosest = true, Order? order = null, bool storeDistances = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoSearchAndStoreAsync(sourceKey, destinationKey, longitude, latitude, shape, count, demandClosest, order, storeDistances, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Geo.cs b/src/StackExchange.Redis/MultiGroupDatabase.Geo.cs new file mode 100644 index 000000000..27e17f062 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Geo.cs @@ -0,0 +1,50 @@ +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // Geo operations + public bool GeoAdd(RedisKey key, double longitude, double latitude, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoAdd(key, longitude, latitude, member, flags); + + public bool GeoAdd(RedisKey key, GeoEntry value, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoAdd(key, value, flags); + + public long GeoAdd(RedisKey key, GeoEntry[] values, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoAdd(key, values, flags); + + public bool GeoRemove(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoRemove(key, member, flags); + + public double? GeoDistance(RedisKey key, RedisValue member1, RedisValue member2, GeoUnit unit = GeoUnit.Meters, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoDistance(key, member1, member2, unit, flags); + + public string?[] GeoHash(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoHash(key, members, flags); + + public string? GeoHash(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoHash(key, member, flags); + + public GeoPosition?[] GeoPosition(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoPosition(key, members, flags); + + public GeoPosition? GeoPosition(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoPosition(key, member, flags); + + public GeoRadiusResult[] GeoRadius(RedisKey key, RedisValue member, double radius, GeoUnit unit = GeoUnit.Meters, int count = -1, Order? order = null, GeoRadiusOptions options = GeoRadiusOptions.Default, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoRadius(key, member, radius, unit, count, order, options, flags); + + public GeoRadiusResult[] GeoRadius(RedisKey key, double longitude, double latitude, double radius, GeoUnit unit = GeoUnit.Meters, int count = -1, Order? order = null, GeoRadiusOptions options = GeoRadiusOptions.Default, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoRadius(key, longitude, latitude, radius, unit, count, order, options, flags); + + public GeoRadiusResult[] GeoSearch(RedisKey key, RedisValue member, GeoSearchShape shape, int count = -1, bool demandClosest = true, Order? order = null, GeoRadiusOptions options = GeoRadiusOptions.Default, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoSearch(key, member, shape, count, demandClosest, order, options, flags); + + public GeoRadiusResult[] GeoSearch(RedisKey key, double longitude, double latitude, GeoSearchShape shape, int count = -1, bool demandClosest = true, Order? order = null, GeoRadiusOptions options = GeoRadiusOptions.Default, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoSearch(key, longitude, latitude, shape, count, demandClosest, order, options, flags); + + public long GeoSearchAndStore(RedisKey sourceKey, RedisKey destinationKey, RedisValue member, GeoSearchShape shape, int count = -1, bool demandClosest = true, Order? order = null, bool storeDistances = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoSearchAndStore(sourceKey, destinationKey, member, shape, count, demandClosest, order, storeDistances, flags); + + public long GeoSearchAndStore(RedisKey sourceKey, RedisKey destinationKey, double longitude, double latitude, GeoSearchShape shape, int count = -1, bool demandClosest = true, Order? order = null, bool storeDistances = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().GeoSearchAndStore(sourceKey, destinationKey, longitude, latitude, shape, count, demandClosest, order, storeDistances, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Hashes.Async.cs b/src/StackExchange.Redis/MultiGroupDatabase.Hashes.Async.cs new file mode 100644 index 000000000..f363c1703 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Hashes.Async.cs @@ -0,0 +1,128 @@ +using System; +using System.Threading.Tasks; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // Hash Async + public Task HashDecrementAsync(RedisKey key, RedisValue hashField, long value = 1, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashDecrementAsync(key, hashField, value, flags); + + public Task HashDecrementAsync(RedisKey key, RedisValue hashField, double value, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashDecrementAsync(key, hashField, value, flags); + + public Task HashDeleteAsync(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashDeleteAsync(key, hashField, flags); + + public Task HashDeleteAsync(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashDeleteAsync(key, hashFields, flags); + + public Task HashExistsAsync(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashExistsAsync(key, hashField, flags); + + public Task HashFieldExpireAsync(RedisKey key, RedisValue[] hashFields, TimeSpan expiry, ExpireWhen when = ExpireWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldExpireAsync(key, hashFields, expiry, when, flags); + + public Task HashFieldExpireAsync(RedisKey key, RedisValue[] hashFields, DateTime expiry, ExpireWhen when = ExpireWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldExpireAsync(key, hashFields, expiry, when, flags); + + public Task HashFieldGetExpireDateTimeAsync(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetExpireDateTimeAsync(key, hashFields, flags); + + public Task HashFieldPersistAsync(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldPersistAsync(key, hashFields, flags); + + public Task HashFieldGetTimeToLiveAsync(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetTimeToLiveAsync(key, hashFields, flags); + + public Task HashGetAsync(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashGetAsync(key, hashField, flags); + + public Task?> HashGetLeaseAsync(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashGetLeaseAsync(key, hashField, flags); + + public Task HashGetAsync(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashGetAsync(key, hashFields, flags); + + public Task HashFieldGetAndDeleteAsync(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetAndDeleteAsync(key, hashField, flags); + + public Task?> HashFieldGetLeaseAndDeleteAsync(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetLeaseAndDeleteAsync(key, hashField, flags); + + public Task HashFieldGetAndDeleteAsync(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetAndDeleteAsync(key, hashFields, flags); + + public Task HashFieldGetAndSetExpiryAsync(RedisKey key, RedisValue hashField, TimeSpan? expiry = null, bool persist = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetAndSetExpiryAsync(key, hashField, expiry, persist, flags); + + public Task HashFieldGetAndSetExpiryAsync(RedisKey key, RedisValue hashField, DateTime expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetAndSetExpiryAsync(key, hashField, expiry, flags); + + public Task?> HashFieldGetLeaseAndSetExpiryAsync(RedisKey key, RedisValue hashField, TimeSpan? expiry = null, bool persist = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetLeaseAndSetExpiryAsync(key, hashField, expiry, persist, flags); + + public Task?> HashFieldGetLeaseAndSetExpiryAsync(RedisKey key, RedisValue hashField, DateTime expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetLeaseAndSetExpiryAsync(key, hashField, expiry, flags); + + public Task HashFieldGetAndSetExpiryAsync(RedisKey key, RedisValue[] hashFields, TimeSpan? expiry = null, bool persist = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetAndSetExpiryAsync(key, hashFields, expiry, persist, flags); + + public Task HashFieldGetAndSetExpiryAsync(RedisKey key, RedisValue[] hashFields, DateTime expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetAndSetExpiryAsync(key, hashFields, expiry, flags); + + public Task HashFieldSetAndSetExpiryAsync(RedisKey key, RedisValue field, RedisValue value, TimeSpan? expiry = null, bool keepTtl = false, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldSetAndSetExpiryAsync(key, field, value, expiry, keepTtl, when, flags); + + public Task HashFieldSetAndSetExpiryAsync(RedisKey key, RedisValue field, RedisValue value, DateTime expiry, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldSetAndSetExpiryAsync(key, field, value, expiry, when, flags); + + public Task HashFieldSetAndSetExpiryAsync(RedisKey key, HashEntry[] hashFields, TimeSpan? expiry = null, bool keepTtl = false, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldSetAndSetExpiryAsync(key, hashFields, expiry, keepTtl, when, flags); + + public Task HashFieldSetAndSetExpiryAsync(RedisKey key, HashEntry[] hashFields, DateTime expiry, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldSetAndSetExpiryAsync(key, hashFields, expiry, when, flags); + + public Task HashGetAllAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashGetAllAsync(key, flags); + + public Task HashIncrementAsync(RedisKey key, RedisValue hashField, long value = 1, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashIncrementAsync(key, hashField, value, flags); + + public Task HashIncrementAsync(RedisKey key, RedisValue hashField, double value, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashIncrementAsync(key, hashField, value, flags); + + public Task HashKeysAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashKeysAsync(key, flags); + + public Task HashLengthAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashLengthAsync(key, flags); + + public Task HashRandomFieldAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashRandomFieldAsync(key, flags); + + public Task HashRandomFieldsAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashRandomFieldsAsync(key, count, flags); + + public Task HashRandomFieldsWithValuesAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashRandomFieldsWithValuesAsync(key, count, flags); + + public System.Collections.Generic.IAsyncEnumerable HashScanAsync(RedisKey key, RedisValue pattern = default, int pageSize = RedisBase.CursorUtils.DefaultLibraryPageSize, long cursor = RedisBase.CursorUtils.Origin, int pageOffset = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashScanAsync(key, pattern, pageSize, cursor, pageOffset, flags); + + public System.Collections.Generic.IAsyncEnumerable HashScanNoValuesAsync(RedisKey key, RedisValue pattern = default, int pageSize = RedisBase.CursorUtils.DefaultLibraryPageSize, long cursor = RedisBase.CursorUtils.Origin, int pageOffset = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashScanNoValuesAsync(key, pattern, pageSize, cursor, pageOffset, flags); + + public Task HashSetAsync(RedisKey key, RedisValue hashField, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashSetAsync(key, hashField, value, when, flags); + + public Task HashSetAsync(RedisKey key, HashEntry[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashSetAsync(key, hashFields, flags); + + public Task HashStringLengthAsync(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashStringLengthAsync(key, hashField, flags); + + public Task HashValuesAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashValuesAsync(key, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Hashes.cs b/src/StackExchange.Redis/MultiGroupDatabase.Hashes.cs new file mode 100644 index 000000000..03f6edb3d --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Hashes.cs @@ -0,0 +1,130 @@ +using System; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // Hash operations + public long HashDecrement(RedisKey key, RedisValue hashField, long value = 1, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashDecrement(key, hashField, value, flags); + + public double HashDecrement(RedisKey key, RedisValue hashField, double value, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashDecrement(key, hashField, value, flags); + + public bool HashDelete(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashDelete(key, hashField, flags); + + public long HashDelete(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashDelete(key, hashFields, flags); + + public bool HashExists(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashExists(key, hashField, flags); + + public ExpireResult[] HashFieldExpire(RedisKey key, RedisValue[] hashFields, TimeSpan expiry, ExpireWhen when = ExpireWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldExpire(key, hashFields, expiry, when, flags); + + public ExpireResult[] HashFieldExpire(RedisKey key, RedisValue[] hashFields, DateTime expiry, ExpireWhen when = ExpireWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldExpire(key, hashFields, expiry, when, flags); + + public long[] HashFieldGetExpireDateTime(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetExpireDateTime(key, hashFields, flags); + + public PersistResult[] HashFieldPersist(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldPersist(key, hashFields, flags); + + public long[] HashFieldGetTimeToLive(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetTimeToLive(key, hashFields, flags); + + public RedisValue HashGet(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashGet(key, hashField, flags); + + public Lease? HashGetLease(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashGetLease(key, hashField, flags); + + public RedisValue[] HashGet(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashGet(key, hashFields, flags); + + public RedisValue HashFieldGetAndDelete(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetAndDelete(key, hashField, flags); + + public Lease? HashFieldGetLeaseAndDelete(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetLeaseAndDelete(key, hashField, flags); + + public RedisValue[] HashFieldGetAndDelete(RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetAndDelete(key, hashFields, flags); + + public RedisValue HashFieldGetAndSetExpiry(RedisKey key, RedisValue hashField, TimeSpan? expiry = null, bool persist = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetAndSetExpiry(key, hashField, expiry, persist, flags); + + public RedisValue HashFieldGetAndSetExpiry(RedisKey key, RedisValue hashField, DateTime expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetAndSetExpiry(key, hashField, expiry, flags); + + public Lease? HashFieldGetLeaseAndSetExpiry(RedisKey key, RedisValue hashField, TimeSpan? expiry = null, bool persist = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetLeaseAndSetExpiry(key, hashField, expiry, persist, flags); + + public Lease? HashFieldGetLeaseAndSetExpiry(RedisKey key, RedisValue hashField, DateTime expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetLeaseAndSetExpiry(key, hashField, expiry, flags); + + public RedisValue[] HashFieldGetAndSetExpiry(RedisKey key, RedisValue[] hashFields, TimeSpan? expiry = null, bool persist = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetAndSetExpiry(key, hashFields, expiry, persist, flags); + + public RedisValue[] HashFieldGetAndSetExpiry(RedisKey key, RedisValue[] hashFields, DateTime expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldGetAndSetExpiry(key, hashFields, expiry, flags); + + public RedisValue HashFieldSetAndSetExpiry(RedisKey key, RedisValue field, RedisValue value, TimeSpan? expiry = null, bool keepTtl = false, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldSetAndSetExpiry(key, field, value, expiry, keepTtl, when, flags); + + public RedisValue HashFieldSetAndSetExpiry(RedisKey key, RedisValue field, RedisValue value, DateTime expiry, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldSetAndSetExpiry(key, field, value, expiry, when, flags); + + public RedisValue HashFieldSetAndSetExpiry(RedisKey key, HashEntry[] hashFields, TimeSpan? expiry = null, bool keepTtl = false, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldSetAndSetExpiry(key, hashFields, expiry, keepTtl, when, flags); + + public RedisValue HashFieldSetAndSetExpiry(RedisKey key, HashEntry[] hashFields, DateTime expiry, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashFieldSetAndSetExpiry(key, hashFields, expiry, when, flags); + + public HashEntry[] HashGetAll(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashGetAll(key, flags); + + public long HashIncrement(RedisKey key, RedisValue hashField, long value = 1, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashIncrement(key, hashField, value, flags); + + public double HashIncrement(RedisKey key, RedisValue hashField, double value, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashIncrement(key, hashField, value, flags); + + public RedisValue[] HashKeys(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashKeys(key, flags); + + public long HashLength(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashLength(key, flags); + + public RedisValue HashRandomField(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashRandomField(key, flags); + + public RedisValue[] HashRandomFields(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashRandomFields(key, count, flags); + + public HashEntry[] HashRandomFieldsWithValues(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashRandomFieldsWithValues(key, count, flags); + + public System.Collections.Generic.IEnumerable HashScan(RedisKey key, RedisValue pattern, int pageSize, CommandFlags flags) + => GetDatabase().HashScan(key, pattern, pageSize, flags); + + public System.Collections.Generic.IEnumerable HashScan(RedisKey key, RedisValue pattern = default, int pageSize = RedisBase.CursorUtils.DefaultLibraryPageSize, long cursor = RedisBase.CursorUtils.Origin, int pageOffset = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashScan(key, pattern, pageSize, cursor, pageOffset, flags); + + public System.Collections.Generic.IEnumerable HashScanNoValues(RedisKey key, RedisValue pattern = default, int pageSize = RedisBase.CursorUtils.DefaultLibraryPageSize, long cursor = RedisBase.CursorUtils.Origin, int pageOffset = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashScanNoValues(key, pattern, pageSize, cursor, pageOffset, flags); + + public bool HashSet(RedisKey key, RedisValue hashField, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashSet(key, hashField, value, when, flags); + + public void HashSet(RedisKey key, HashEntry[] hashFields, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashSet(key, hashFields, flags); + + public long HashStringLength(RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashStringLength(key, hashField, flags); + + public RedisValue[] HashValues(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().HashValues(key, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.HyperLogLog.Async.cs b/src/StackExchange.Redis/MultiGroupDatabase.HyperLogLog.Async.cs new file mode 100644 index 000000000..8cf7eac2e --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.HyperLogLog.Async.cs @@ -0,0 +1,25 @@ +using System.Threading.Tasks; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // HyperLogLog Async + public Task HyperLogLogAddAsync(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().HyperLogLogAddAsync(key, value, flags); + + public Task HyperLogLogAddAsync(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) + => GetDatabase().HyperLogLogAddAsync(key, values, flags); + + public Task HyperLogLogLengthAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().HyperLogLogLengthAsync(key, flags); + + public Task HyperLogLogLengthAsync(RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().HyperLogLogLengthAsync(keys, flags); + + public Task HyperLogLogMergeAsync(RedisKey destination, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None) + => GetDatabase().HyperLogLogMergeAsync(destination, first, second, flags); + + public Task HyperLogLogMergeAsync(RedisKey destination, RedisKey[] sourceKeys, CommandFlags flags = CommandFlags.None) + => GetDatabase().HyperLogLogMergeAsync(destination, sourceKeys, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.HyperLogLog.cs b/src/StackExchange.Redis/MultiGroupDatabase.HyperLogLog.cs new file mode 100644 index 000000000..b71967077 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.HyperLogLog.cs @@ -0,0 +1,23 @@ +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // HyperLogLog operations + public bool HyperLogLogAdd(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().HyperLogLogAdd(key, value, flags); + + public bool HyperLogLogAdd(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) + => GetDatabase().HyperLogLogAdd(key, values, flags); + + public long HyperLogLogLength(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().HyperLogLogLength(key, flags); + + public long HyperLogLogLength(RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().HyperLogLogLength(keys, flags); + + public void HyperLogLogMerge(RedisKey destination, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None) + => GetDatabase().HyperLogLogMerge(destination, first, second, flags); + + public void HyperLogLogMerge(RedisKey destination, RedisKey[] sourceKeys, CommandFlags flags = CommandFlags.None) + => GetDatabase().HyperLogLogMerge(destination, sourceKeys, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Keys.Async.cs b/src/StackExchange.Redis/MultiGroupDatabase.Keys.Async.cs new file mode 100644 index 000000000..f3d044a57 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Keys.Async.cs @@ -0,0 +1,80 @@ +using System; +using System.Threading.Tasks; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // Key Async + public Task KeyCopyAsync(RedisKey sourceKey, RedisKey destinationKey, int destinationDatabase = -1, bool replace = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyCopyAsync(sourceKey, destinationKey, destinationDatabase, replace, flags); + + public Task KeyDeleteAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyDeleteAsync(key, flags); + + public Task KeyDeleteAsync(RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyDeleteAsync(keys, flags); + + public Task KeyDumpAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyDumpAsync(key, flags); + + public Task KeyEncodingAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyEncodingAsync(key, flags); + + public Task KeyExistsAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyExistsAsync(key, flags); + + public Task KeyExistsAsync(RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyExistsAsync(keys, flags); + + public Task KeyExpireAsync(RedisKey key, TimeSpan? expiry, CommandFlags flags) + => GetDatabase().KeyExpireAsync(key, expiry, flags); + + public Task KeyExpireAsync(RedisKey key, TimeSpan? expiry, ExpireWhen when = ExpireWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyExpireAsync(key, expiry, when, flags); + + public Task KeyExpireAsync(RedisKey key, DateTime? expiry, CommandFlags flags) + => GetDatabase().KeyExpireAsync(key, expiry, flags); + + public Task KeyExpireAsync(RedisKey key, DateTime? expiry, ExpireWhen when = ExpireWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyExpireAsync(key, expiry, when, flags); + + public Task KeyExpireTimeAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyExpireTimeAsync(key, flags); + + public Task KeyFrequencyAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyFrequencyAsync(key, flags); + + public Task KeyIdleTimeAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyIdleTimeAsync(key, flags); + + public Task KeyMoveAsync(RedisKey key, int database, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyMoveAsync(key, database, flags); + + public Task KeyPersistAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyPersistAsync(key, flags); + + public Task KeyRandomAsync(CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyRandomAsync(flags); + + public Task KeyRefCountAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyRefCountAsync(key, flags); + + public Task KeyRenameAsync(RedisKey key, RedisKey newKey, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyRenameAsync(key, newKey, when, flags); + + public Task KeyRestoreAsync(RedisKey key, byte[] value, TimeSpan? expiry = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyRestoreAsync(key, value, expiry, flags); + + public Task KeyTimeToLiveAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyTimeToLiveAsync(key, flags); + + public Task KeyTouchAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyTouchAsync(key, flags); + + public Task KeyTouchAsync(RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyTouchAsync(keys, flags); + + public Task KeyTypeAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyTypeAsync(key, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Keys.cs b/src/StackExchange.Redis/MultiGroupDatabase.Keys.cs new file mode 100644 index 000000000..da192f703 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Keys.cs @@ -0,0 +1,79 @@ +using System; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // Key operations + public bool KeyCopy(RedisKey sourceKey, RedisKey destinationKey, int destinationDatabase = -1, bool replace = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyCopy(sourceKey, destinationKey, destinationDatabase, replace, flags); + + public bool KeyDelete(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyDelete(key, flags); + + public long KeyDelete(RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyDelete(keys, flags); + + public byte[]? KeyDump(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyDump(key, flags); + + public string? KeyEncoding(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyEncoding(key, flags); + + public bool KeyExists(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyExists(key, flags); + + public long KeyExists(RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyExists(keys, flags); + + public bool KeyExpire(RedisKey key, TimeSpan? expiry, CommandFlags flags) + => GetDatabase().KeyExpire(key, expiry, flags); + + public bool KeyExpire(RedisKey key, TimeSpan? expiry, ExpireWhen when = ExpireWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyExpire(key, expiry, when, flags); + + public bool KeyExpire(RedisKey key, DateTime? expiry, CommandFlags flags) + => GetDatabase().KeyExpire(key, expiry, flags); + + public bool KeyExpire(RedisKey key, DateTime? expiry, ExpireWhen when = ExpireWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyExpire(key, expiry, when, flags); + + public DateTime? KeyExpireTime(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyExpireTime(key, flags); + + public long? KeyFrequency(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyFrequency(key, flags); + + public TimeSpan? KeyIdleTime(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyIdleTime(key, flags); + + public bool KeyMove(RedisKey key, int database, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyMove(key, database, flags); + + public bool KeyPersist(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyPersist(key, flags); + + public RedisKey KeyRandom(CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyRandom(flags); + + public long? KeyRefCount(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyRefCount(key, flags); + + public bool KeyRename(RedisKey key, RedisKey newKey, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyRename(key, newKey, when, flags); + + public void KeyRestore(RedisKey key, byte[] value, TimeSpan? expiry = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyRestore(key, value, expiry, flags); + + public TimeSpan? KeyTimeToLive(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyTimeToLive(key, flags); + + public bool KeyTouch(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyTouch(key, flags); + + public long KeyTouch(RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyTouch(keys, flags); + + public RedisType KeyType(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyType(key, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Lists.Async.cs b/src/StackExchange.Redis/MultiGroupDatabase.Lists.Async.cs new file mode 100644 index 000000000..078a99643 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Lists.Async.cs @@ -0,0 +1,79 @@ +using System.Threading.Tasks; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // List Async operations + public Task ListGetByIndexAsync(RedisKey key, long index, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListGetByIndexAsync(key, index, flags); + + public Task ListInsertAfterAsync(RedisKey key, RedisValue pivot, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListInsertAfterAsync(key, pivot, value, flags); + + public Task ListInsertBeforeAsync(RedisKey key, RedisValue pivot, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListInsertBeforeAsync(key, pivot, value, flags); + + public Task ListLeftPopAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListLeftPopAsync(key, flags); + + public Task ListLeftPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListLeftPopAsync(key, count, flags); + + public Task ListLeftPopAsync(RedisKey[] keys, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListLeftPopAsync(keys, count, flags); + + public Task ListLeftPushAsync(RedisKey key, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListLeftPushAsync(key, value, when, flags); + + public Task ListLeftPushAsync(RedisKey key, RedisValue[] values, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListLeftPushAsync(key, values, when, flags); + + public Task ListLeftPushAsync(RedisKey key, RedisValue[] values, CommandFlags flags) + => GetDatabase().ListLeftPushAsync(key, values, flags); + + public Task ListLengthAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListLengthAsync(key, flags); + + public Task ListMoveAsync(RedisKey sourceKey, RedisKey destinationKey, ListSide sourceSide, ListSide destinationSide, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListMoveAsync(sourceKey, destinationKey, sourceSide, destinationSide, flags); + + public Task ListPositionAsync(RedisKey key, RedisValue element, long rank = 1, long maxLength = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListPositionAsync(key, element, rank, maxLength, flags); + + public Task ListPositionsAsync(RedisKey key, RedisValue element, long count, long rank = 1, long maxLength = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListPositionsAsync(key, element, count, rank, maxLength, flags); + + public Task ListRangeAsync(RedisKey key, long start = 0, long stop = -1, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRangeAsync(key, start, stop, flags); + + public Task ListRemoveAsync(RedisKey key, RedisValue value, long count = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRemoveAsync(key, value, count, flags); + + public Task ListRightPopAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRightPopAsync(key, flags); + + public Task ListRightPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRightPopAsync(key, count, flags); + + public Task ListRightPopAsync(RedisKey[] keys, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRightPopAsync(keys, count, flags); + + public Task ListRightPopLeftPushAsync(RedisKey source, RedisKey destination, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRightPopLeftPushAsync(source, destination, flags); + + public Task ListRightPushAsync(RedisKey key, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRightPushAsync(key, value, when, flags); + + public Task ListRightPushAsync(RedisKey key, RedisValue[] values, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRightPushAsync(key, values, when, flags); + + public Task ListRightPushAsync(RedisKey key, RedisValue[] values, CommandFlags flags) + => GetDatabase().ListRightPushAsync(key, values, flags); + + public Task ListSetByIndexAsync(RedisKey key, long index, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListSetByIndexAsync(key, index, value, flags); + + public Task ListTrimAsync(RedisKey key, long start, long stop, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListTrimAsync(key, start, stop, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Lists.cs b/src/StackExchange.Redis/MultiGroupDatabase.Lists.cs new file mode 100644 index 000000000..eca3cacbe --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Lists.cs @@ -0,0 +1,77 @@ +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // List operations + public RedisValue ListGetByIndex(RedisKey key, long index, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListGetByIndex(key, index, flags); + + public long ListInsertAfter(RedisKey key, RedisValue pivot, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListInsertAfter(key, pivot, value, flags); + + public long ListInsertBefore(RedisKey key, RedisValue pivot, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListInsertBefore(key, pivot, value, flags); + + public RedisValue ListLeftPop(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListLeftPop(key, flags); + + public RedisValue[] ListLeftPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListLeftPop(key, count, flags); + + public ListPopResult ListLeftPop(RedisKey[] keys, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListLeftPop(keys, count, flags); + + public long ListLeftPush(RedisKey key, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListLeftPush(key, value, when, flags); + + public long ListLeftPush(RedisKey key, RedisValue[] values, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListLeftPush(key, values, when, flags); + + public long ListLeftPush(RedisKey key, RedisValue[] values, CommandFlags flags) + => GetDatabase().ListLeftPush(key, values, flags); + + public long ListLength(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListLength(key, flags); + + public RedisValue ListMove(RedisKey sourceKey, RedisKey destinationKey, ListSide sourceSide, ListSide destinationSide, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListMove(sourceKey, destinationKey, sourceSide, destinationSide, flags); + + public long ListPosition(RedisKey key, RedisValue element, long rank = 1, long maxLength = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListPosition(key, element, rank, maxLength, flags); + + public long[] ListPositions(RedisKey key, RedisValue element, long count, long rank = 1, long maxLength = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListPositions(key, element, count, rank, maxLength, flags); + + public RedisValue[] ListRange(RedisKey key, long start = 0, long stop = -1, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRange(key, start, stop, flags); + + public long ListRemove(RedisKey key, RedisValue value, long count = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRemove(key, value, count, flags); + + public RedisValue ListRightPop(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRightPop(key, flags); + + public RedisValue[] ListRightPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRightPop(key, count, flags); + + public ListPopResult ListRightPop(RedisKey[] keys, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRightPop(keys, count, flags); + + public RedisValue ListRightPopLeftPush(RedisKey source, RedisKey destination, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRightPopLeftPush(source, destination, flags); + + public long ListRightPush(RedisKey key, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRightPush(key, value, when, flags); + + public long ListRightPush(RedisKey key, RedisValue[] values, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListRightPush(key, values, when, flags); + + public long ListRightPush(RedisKey key, RedisValue[] values, CommandFlags flags) + => GetDatabase().ListRightPush(key, values, flags); + + public void ListSetByIndex(RedisKey key, long index, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListSetByIndex(key, index, value, flags); + + public void ListTrim(RedisKey key, long start, long stop, CommandFlags flags = CommandFlags.None) + => GetDatabase().ListTrim(key, start, stop, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Sets.Async.cs b/src/StackExchange.Redis/MultiGroupDatabase.Sets.Async.cs new file mode 100644 index 000000000..db8ae3043 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Sets.Async.cs @@ -0,0 +1,64 @@ +using System.Threading.Tasks; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // Set Async operations + public Task SetAddAsync(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetAddAsync(key, value, flags); + + public Task SetAddAsync(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetAddAsync(key, values, flags); + + public Task SetCombineAsync(SetOperation operation, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetCombineAsync(operation, first, second, flags); + + public Task SetCombineAsync(SetOperation operation, RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetCombineAsync(operation, keys, flags); + + public Task SetCombineAndStoreAsync(SetOperation operation, RedisKey destination, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetCombineAndStoreAsync(operation, destination, first, second, flags); + + public Task SetCombineAndStoreAsync(SetOperation operation, RedisKey destination, RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetCombineAndStoreAsync(operation, destination, keys, flags); + + public Task SetContainsAsync(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetContainsAsync(key, value, flags); + + public Task SetContainsAsync(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetContainsAsync(key, values, flags); + + public Task SetIntersectionLengthAsync(RedisKey[] keys, long limit = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetIntersectionLengthAsync(keys, limit, flags); + + public Task SetLengthAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetLengthAsync(key, flags); + + public Task SetMembersAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetMembersAsync(key, flags); + + public Task SetMoveAsync(RedisKey source, RedisKey destination, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetMoveAsync(source, destination, value, flags); + + public Task SetPopAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetPopAsync(key, flags); + + public Task SetPopAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetPopAsync(key, count, flags); + + public Task SetRandomMemberAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetRandomMemberAsync(key, flags); + + public Task SetRandomMembersAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetRandomMembersAsync(key, count, flags); + + public Task SetRemoveAsync(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetRemoveAsync(key, value, flags); + + public Task SetRemoveAsync(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetRemoveAsync(key, values, flags); + + public System.Collections.Generic.IAsyncEnumerable SetScanAsync(RedisKey key, RedisValue pattern = default, int pageSize = RedisBase.CursorUtils.DefaultLibraryPageSize, long cursor = RedisBase.CursorUtils.Origin, int pageOffset = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetScanAsync(key, pattern, pageSize, cursor, pageOffset, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Sets.cs b/src/StackExchange.Redis/MultiGroupDatabase.Sets.cs new file mode 100644 index 000000000..8f99993ea --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Sets.cs @@ -0,0 +1,65 @@ +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // Set operations + public bool SetAdd(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetAdd(key, value, flags); + + public long SetAdd(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetAdd(key, values, flags); + + public RedisValue[] SetCombine(SetOperation operation, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetCombine(operation, first, second, flags); + + public RedisValue[] SetCombine(SetOperation operation, RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetCombine(operation, keys, flags); + + public long SetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetCombineAndStore(operation, destination, first, second, flags); + + public long SetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetCombineAndStore(operation, destination, keys, flags); + + public bool SetContains(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetContains(key, value, flags); + + public bool[] SetContains(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetContains(key, values, flags); + + public long SetIntersectionLength(RedisKey[] keys, long limit = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetIntersectionLength(keys, limit, flags); + + public long SetLength(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetLength(key, flags); + + public RedisValue[] SetMembers(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetMembers(key, flags); + + public bool SetMove(RedisKey source, RedisKey destination, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetMove(source, destination, value, flags); + + public RedisValue SetPop(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetPop(key, flags); + + public RedisValue[] SetPop(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetPop(key, count, flags); + + public RedisValue SetRandomMember(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetRandomMember(key, flags); + + public RedisValue[] SetRandomMembers(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetRandomMembers(key, count, flags); + + public bool SetRemove(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetRemove(key, value, flags); + + public long SetRemove(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetRemove(key, values, flags); + + public System.Collections.Generic.IEnumerable SetScan(RedisKey key, RedisValue pattern, int pageSize, CommandFlags flags) + => GetDatabase().SetScan(key, pattern, pageSize, flags); + + public System.Collections.Generic.IEnumerable SetScan(RedisKey key, RedisValue pattern = default, int pageSize = RedisBase.CursorUtils.DefaultLibraryPageSize, long cursor = RedisBase.CursorUtils.Origin, int pageOffset = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().SetScan(key, pattern, pageSize, cursor, pageOffset, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.SortedSets.Async.cs b/src/StackExchange.Redis/MultiGroupDatabase.SortedSets.Async.cs new file mode 100644 index 000000000..0fc0ea73b --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.SortedSets.Async.cs @@ -0,0 +1,124 @@ +using System.Threading.Tasks; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // SortedSet Async operations + public Task SortedSetAddAsync(RedisKey key, RedisValue member, double score, CommandFlags flags) + => GetDatabase().SortedSetAddAsync(key, member, score, flags); + + public Task SortedSetAddAsync(RedisKey key, RedisValue member, double score, When when, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetAddAsync(key, member, score, when, flags); + + public Task SortedSetAddAsync(RedisKey key, RedisValue member, double score, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetAddAsync(key, member, score, when, flags); + + public Task SortedSetAddAsync(RedisKey key, SortedSetEntry[] values, CommandFlags flags) + => GetDatabase().SortedSetAddAsync(key, values, flags); + + public Task SortedSetAddAsync(RedisKey key, SortedSetEntry[] values, When when, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetAddAsync(key, values, when, flags); + + public Task SortedSetAddAsync(RedisKey key, SortedSetEntry[] values, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetAddAsync(key, values, when, flags); + + public Task SortedSetCombineAsync(SetOperation operation, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetCombineAsync(operation, keys, weights, aggregate, flags); + + public Task SortedSetCombineWithScoresAsync(SetOperation operation, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetCombineWithScoresAsync(operation, keys, weights, aggregate, flags); + + public Task SortedSetCombineAndStoreAsync(SetOperation operation, RedisKey destination, RedisKey first, RedisKey second, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetCombineAndStoreAsync(operation, destination, first, second, aggregate, flags); + + public Task SortedSetCombineAndStoreAsync(SetOperation operation, RedisKey destination, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetCombineAndStoreAsync(operation, destination, keys, weights, aggregate, flags); + + public Task SortedSetDecrementAsync(RedisKey key, RedisValue member, double value, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetDecrementAsync(key, member, value, flags); + + public Task SortedSetIncrementAsync(RedisKey key, RedisValue member, double value, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetIncrementAsync(key, member, value, flags); + + public Task SortedSetIntersectionLengthAsync(RedisKey[] keys, long limit = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetIntersectionLengthAsync(keys, limit, flags); + + public Task SortedSetLengthAsync(RedisKey key, double min = double.NegativeInfinity, double max = double.PositiveInfinity, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetLengthAsync(key, min, max, exclude, flags); + + public Task SortedSetLengthByValueAsync(RedisKey key, RedisValue min, RedisValue max, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetLengthByValueAsync(key, min, max, exclude, flags); + + public Task SortedSetRandomMemberAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRandomMemberAsync(key, flags); + + public Task SortedSetRandomMembersAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRandomMembersAsync(key, count, flags); + + public Task SortedSetRandomMembersWithScoresAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRandomMembersWithScoresAsync(key, count, flags); + + public Task SortedSetRangeByRankAsync(RedisKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeByRankAsync(key, start, stop, order, flags); + + public Task SortedSetRangeAndStoreAsync(RedisKey sourceKey, RedisKey destinationKey, RedisValue start, RedisValue stop, SortedSetOrder sortedSetOrder = SortedSetOrder.ByRank, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long? take = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeAndStoreAsync(sourceKey, destinationKey, start, stop, sortedSetOrder, exclude, order, skip, take, flags); + + public Task SortedSetRangeByRankWithScoresAsync(RedisKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeByRankWithScoresAsync(key, start, stop, order, flags); + + public Task SortedSetRangeByScoreAsync(RedisKey key, double start = double.NegativeInfinity, double stop = double.PositiveInfinity, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeByScoreAsync(key, start, stop, exclude, order, skip, take, flags); + + public Task SortedSetRangeByScoreWithScoresAsync(RedisKey key, double start = double.NegativeInfinity, double stop = double.PositiveInfinity, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeByScoreWithScoresAsync(key, start, stop, exclude, order, skip, take, flags); + + public Task SortedSetRangeByValueAsync(RedisKey key, RedisValue min, RedisValue max, Exclude exclude, long skip, long take = -1, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeByValueAsync(key, min, max, exclude, skip, take, flags); + + public Task SortedSetRangeByValueAsync(RedisKey key, RedisValue min = default, RedisValue max = default, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeByValueAsync(key, min, max, exclude, order, skip, take, flags); + + public Task SortedSetRankAsync(RedisKey key, RedisValue member, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRankAsync(key, member, order, flags); + + public Task SortedSetRemoveAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRemoveAsync(key, member, flags); + + public Task SortedSetRemoveAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRemoveAsync(key, members, flags); + + public Task SortedSetRemoveRangeByRankAsync(RedisKey key, long start, long stop, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRemoveRangeByRankAsync(key, start, stop, flags); + + public Task SortedSetRemoveRangeByScoreAsync(RedisKey key, double start, double stop, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRemoveRangeByScoreAsync(key, start, stop, exclude, flags); + + public Task SortedSetRemoveRangeByValueAsync(RedisKey key, RedisValue min, RedisValue max, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRemoveRangeByValueAsync(key, min, max, exclude, flags); + + public System.Collections.Generic.IAsyncEnumerable SortedSetScanAsync(RedisKey key, RedisValue pattern = default, int pageSize = RedisBase.CursorUtils.DefaultLibraryPageSize, long cursor = RedisBase.CursorUtils.Origin, int pageOffset = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetScanAsync(key, pattern, pageSize, cursor, pageOffset, flags); + + public Task SortedSetScoreAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetScoreAsync(key, member, flags); + + public Task SortedSetScoresAsync(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetScoresAsync(key, members, flags); + + public Task SortedSetPopAsync(RedisKey key, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetPopAsync(key, order, flags); + + public Task SortedSetPopAsync(RedisKey key, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetPopAsync(key, count, order, flags); + + public Task SortedSetPopAsync(RedisKey[] keys, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetPopAsync(keys, count, order, flags); + + public Task SortedSetUpdateAsync(RedisKey key, RedisValue member, double score, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetUpdateAsync(key, member, score, when, flags); + + public Task SortedSetUpdateAsync(RedisKey key, SortedSetEntry[] values, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetUpdateAsync(key, values, when, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.SortedSets.cs b/src/StackExchange.Redis/MultiGroupDatabase.SortedSets.cs new file mode 100644 index 000000000..73f7567b7 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.SortedSets.cs @@ -0,0 +1,127 @@ +using System; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // SortedSet operations + public bool SortedSetAdd(RedisKey key, RedisValue member, double score, CommandFlags flags) + => GetDatabase().SortedSetAdd(key, member, score, flags); + + public bool SortedSetAdd(RedisKey key, RedisValue member, double score, When when, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetAdd(key, member, score, when, flags); + + public bool SortedSetAdd(RedisKey key, RedisValue member, double score, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetAdd(key, member, score, when, flags); + + public long SortedSetAdd(RedisKey key, SortedSetEntry[] values, CommandFlags flags) + => GetDatabase().SortedSetAdd(key, values, flags); + + public long SortedSetAdd(RedisKey key, SortedSetEntry[] values, When when, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetAdd(key, values, when, flags); + + public long SortedSetAdd(RedisKey key, SortedSetEntry[] values, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetAdd(key, values, when, flags); + + public RedisValue[] SortedSetCombine(SetOperation operation, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetCombine(operation, keys, weights, aggregate, flags); + + public SortedSetEntry[] SortedSetCombineWithScores(SetOperation operation, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetCombineWithScores(operation, keys, weights, aggregate, flags); + + public long SortedSetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey first, RedisKey second, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetCombineAndStore(operation, destination, first, second, aggregate, flags); + + public long SortedSetCombineAndStore(SetOperation operation, RedisKey destination, RedisKey[] keys, double[]? weights = null, Aggregate aggregate = Aggregate.Sum, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetCombineAndStore(operation, destination, keys, weights, aggregate, flags); + + public double SortedSetDecrement(RedisKey key, RedisValue member, double value, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetDecrement(key, member, value, flags); + + public double SortedSetIncrement(RedisKey key, RedisValue member, double value, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetIncrement(key, member, value, flags); + + public long SortedSetIntersectionLength(RedisKey[] keys, long limit = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetIntersectionLength(keys, limit, flags); + + public long SortedSetLength(RedisKey key, double min = double.NegativeInfinity, double max = double.PositiveInfinity, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetLength(key, min, max, exclude, flags); + + public long SortedSetLengthByValue(RedisKey key, RedisValue min, RedisValue max, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetLengthByValue(key, min, max, exclude, flags); + + public RedisValue SortedSetRandomMember(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRandomMember(key, flags); + + public RedisValue[] SortedSetRandomMembers(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRandomMembers(key, count, flags); + + public SortedSetEntry[] SortedSetRandomMembersWithScores(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRandomMembersWithScores(key, count, flags); + + public RedisValue[] SortedSetRangeByRank(RedisKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeByRank(key, start, stop, order, flags); + + public long SortedSetRangeAndStore(RedisKey sourceKey, RedisKey destinationKey, RedisValue start, RedisValue stop, SortedSetOrder sortedSetOrder = SortedSetOrder.ByRank, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long? take = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeAndStore(sourceKey, destinationKey, start, stop, sortedSetOrder, exclude, order, skip, take, flags); + + public SortedSetEntry[] SortedSetRangeByRankWithScores(RedisKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeByRankWithScores(key, start, stop, order, flags); + + public RedisValue[] SortedSetRangeByScore(RedisKey key, double start = double.NegativeInfinity, double stop = double.PositiveInfinity, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeByScore(key, start, stop, exclude, order, skip, take, flags); + + public SortedSetEntry[] SortedSetRangeByScoreWithScores(RedisKey key, double start = double.NegativeInfinity, double stop = double.PositiveInfinity, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeByScoreWithScores(key, start, stop, exclude, order, skip, take, flags); + + public RedisValue[] SortedSetRangeByValue(RedisKey key, RedisValue min, RedisValue max, Exclude exclude, long skip, long take = -1, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeByValue(key, min, max, exclude, skip, take, flags); + + public RedisValue[] SortedSetRangeByValue(RedisKey key, RedisValue min = default, RedisValue max = default, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRangeByValue(key, min, max, exclude, order, skip, take, flags); + + public long? SortedSetRank(RedisKey key, RedisValue member, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRank(key, member, order, flags); + + public bool SortedSetRemove(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRemove(key, member, flags); + + public long SortedSetRemove(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRemove(key, members, flags); + + public long SortedSetRemoveRangeByRank(RedisKey key, long start, long stop, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRemoveRangeByRank(key, start, stop, flags); + + public long SortedSetRemoveRangeByScore(RedisKey key, double start, double stop, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRemoveRangeByScore(key, start, stop, exclude, flags); + + public long SortedSetRemoveRangeByValue(RedisKey key, RedisValue min, RedisValue max, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetRemoveRangeByValue(key, min, max, exclude, flags); + + public System.Collections.Generic.IEnumerable SortedSetScan(RedisKey key, RedisValue pattern, int pageSize, CommandFlags flags) + => GetDatabase().SortedSetScan(key, pattern, pageSize, flags); + + public System.Collections.Generic.IEnumerable SortedSetScan(RedisKey key, RedisValue pattern = default, int pageSize = RedisBase.CursorUtils.DefaultLibraryPageSize, long cursor = RedisBase.CursorUtils.Origin, int pageOffset = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetScan(key, pattern, pageSize, cursor, pageOffset, flags); + + public double? SortedSetScore(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetScore(key, member, flags); + + public double?[] SortedSetScores(RedisKey key, RedisValue[] members, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetScores(key, members, flags); + + public SortedSetEntry? SortedSetPop(RedisKey key, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetPop(key, order, flags); + + public SortedSetEntry[] SortedSetPop(RedisKey key, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetPop(key, count, order, flags); + + public SortedSetPopResult SortedSetPop(RedisKey[] keys, long count, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetPop(keys, count, order, flags); + + public bool SortedSetUpdate(RedisKey key, RedisValue member, double score, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetUpdate(key, member, score, when, flags); + + public long SortedSetUpdate(RedisKey key, SortedSetEntry[] values, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortedSetUpdate(key, values, when, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Streams.Async.cs b/src/StackExchange.Redis/MultiGroupDatabase.Streams.Async.cs new file mode 100644 index 000000000..81a0c5dd1 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Streams.Async.cs @@ -0,0 +1,122 @@ +using System; +using System.Threading.Tasks; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // Stream Async operations + public Task StreamAutoClaimIdsOnlyAsync(RedisKey key, RedisValue consumerGroup, RedisValue claimingConsumer, long minIdleTimeInMs, RedisValue startAtId, int? count = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAutoClaimIdsOnlyAsync(key, consumerGroup, claimingConsumer, minIdleTimeInMs, startAtId, count, flags); + + public Task StreamAutoClaimAsync(RedisKey key, RedisValue consumerGroup, RedisValue claimingConsumer, long minIdleTimeInMs, RedisValue startAtId, int? count = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAutoClaimAsync(key, consumerGroup, claimingConsumer, minIdleTimeInMs, startAtId, count, flags); + + public Task StreamAddAsync(RedisKey key, RedisValue streamField, RedisValue streamValue, RedisValue? messageId = null, int? maxLength = null, bool useApproximateMaxLength = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAddAsync(key, streamField, streamValue, messageId, maxLength, useApproximateMaxLength, flags); + + public Task StreamAddAsync(RedisKey key, RedisValue streamField, RedisValue streamValue, RedisValue? messageId = null, long? maxLength = null, bool useApproximateMaxLength = false, long? limit = null, StreamTrimMode trimMode = StreamTrimMode.KeepReferences, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAddAsync(key, streamField, streamValue, messageId, maxLength, useApproximateMaxLength, limit, trimMode, flags); + + public Task StreamAddAsync(RedisKey key, NameValueEntry[] streamPairs, RedisValue? messageId = null, int? maxLength = null, bool useApproximateMaxLength = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAddAsync(key, streamPairs, messageId, maxLength, useApproximateMaxLength, flags); + + public Task StreamAddAsync(RedisKey key, NameValueEntry[] streamPairs, RedisValue? messageId = null, long? maxLength = null, bool useApproximateMaxLength = false, long? limit = null, StreamTrimMode trimMode = StreamTrimMode.KeepReferences, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAddAsync(key, streamPairs, messageId, maxLength, useApproximateMaxLength, limit, trimMode, flags); + + public Task StreamClaimAsync(RedisKey key, RedisValue consumerGroup, RedisValue claimingConsumer, long minIdleTimeInMs, RedisValue[] messageIds, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamClaimAsync(key, consumerGroup, claimingConsumer, minIdleTimeInMs, messageIds, flags); + + public Task StreamClaimIdsOnlyAsync(RedisKey key, RedisValue consumerGroup, RedisValue claimingConsumer, long minIdleTimeInMs, RedisValue[] messageIds, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamClaimIdsOnlyAsync(key, consumerGroup, claimingConsumer, minIdleTimeInMs, messageIds, flags); + + public Task StreamConsumerGroupSetPositionAsync(RedisKey key, RedisValue groupName, RedisValue position, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamConsumerGroupSetPositionAsync(key, groupName, position, flags); + + public Task StreamConsumerInfoAsync(RedisKey key, RedisValue groupName, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamConsumerInfoAsync(key, groupName, flags); + + public Task StreamCreateConsumerGroupAsync(RedisKey key, RedisValue groupName, RedisValue? position, CommandFlags flags) + => GetDatabase().StreamCreateConsumerGroupAsync(key, groupName, position, flags); + + public Task StreamCreateConsumerGroupAsync(RedisKey key, RedisValue groupName, RedisValue? position = null, bool createStream = true, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamCreateConsumerGroupAsync(key, groupName, position, createStream, flags); + + public Task StreamDeleteAsync(RedisKey key, RedisValue[] messageIds, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamDeleteAsync(key, messageIds, flags); + + public Task StreamDeleteAsync(RedisKey key, RedisValue[] messageIds, StreamTrimMode mode, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamDeleteAsync(key, messageIds, mode, flags); + + public Task StreamDeleteConsumerAsync(RedisKey key, RedisValue groupName, RedisValue consumerName, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamDeleteConsumerAsync(key, groupName, consumerName, flags); + + public Task StreamDeleteConsumerGroupAsync(RedisKey key, RedisValue groupName, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamDeleteConsumerGroupAsync(key, groupName, flags); + + public Task StreamGroupInfoAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamGroupInfoAsync(key, flags); + + public Task StreamInfoAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamInfoAsync(key, flags); + + public Task StreamLengthAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamLengthAsync(key, flags); + + public Task StreamPendingAsync(RedisKey key, RedisValue groupName, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamPendingAsync(key, groupName, flags); + + public Task StreamPendingMessagesAsync(RedisKey key, RedisValue groupName, int count, RedisValue consumerName, RedisValue? minId = null, RedisValue? maxId = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamPendingMessagesAsync(key, groupName, count, consumerName, minId, maxId, flags); + + public Task StreamPendingMessagesAsync(RedisKey key, RedisValue groupName, int count, RedisValue consumerName, RedisValue? minId = null, RedisValue? maxId = null, long? idle = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamPendingMessagesAsync(key, groupName, count, consumerName, minId, maxId, idle, flags); + + public Task StreamRangeAsync(RedisKey key, RedisValue? minId = null, RedisValue? maxId = null, int? count = null, Order messageOrder = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamRangeAsync(key, minId, maxId, count, messageOrder, flags); + + public Task StreamReadAsync(RedisKey key, RedisValue position, int? count = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamReadAsync(key, position, count, flags); + + public Task StreamReadAsync(StreamPosition[] streamPositions, int? countPerStream = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamReadAsync(streamPositions, countPerStream, flags); + + public Task StreamReadGroupAsync(RedisKey key, RedisValue groupName, RedisValue consumerName, RedisValue? position, int? count, CommandFlags flags) + => GetDatabase().StreamReadGroupAsync(key, groupName, consumerName, position, count, flags); + + public Task StreamReadGroupAsync(RedisKey key, RedisValue groupName, RedisValue consumerName, RedisValue? position = null, int? count = null, bool noAck = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamReadGroupAsync(key, groupName, consumerName, position, count, noAck, flags); + + public Task StreamReadGroupAsync(RedisKey key, RedisValue groupName, RedisValue consumerName, RedisValue? position = null, int? count = null, bool noAck = false, TimeSpan? blockingTimeout = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamReadGroupAsync(key, groupName, consumerName, position, count, noAck, blockingTimeout, flags); + + public Task StreamReadGroupAsync(StreamPosition[] streamPositions, RedisValue groupName, RedisValue consumerName, int? countPerStream, CommandFlags flags) + => GetDatabase().StreamReadGroupAsync(streamPositions, groupName, consumerName, countPerStream, flags); + + public Task StreamReadGroupAsync(StreamPosition[] streamPositions, RedisValue groupName, RedisValue consumerName, int? countPerStream = null, bool noAck = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamReadGroupAsync(streamPositions, groupName, consumerName, countPerStream, noAck, flags); + + public Task StreamReadGroupAsync(StreamPosition[] streamPositions, RedisValue groupName, RedisValue consumerName, int? countPerStream = null, bool noAck = false, TimeSpan? blockingTimeout = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamReadGroupAsync(streamPositions, groupName, consumerName, countPerStream, noAck, blockingTimeout, flags); + + public Task StreamTrimAsync(RedisKey key, int maxLength, bool useApproximateMaxLength = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamTrimAsync(key, maxLength, useApproximateMaxLength, flags); + + public Task StreamTrimAsync(RedisKey key, long maxLength, bool useApproximateMaxLength = false, long? limit = null, StreamTrimMode trimMode = StreamTrimMode.KeepReferences, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamTrimAsync(key, maxLength, useApproximateMaxLength, limit, trimMode, flags); + + public Task StreamTrimByMinIdAsync(RedisKey key, RedisValue minId, bool useApproximateMaxLength = false, long? limit = null, StreamTrimMode trimMode = StreamTrimMode.KeepReferences, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamTrimByMinIdAsync(key, minId, useApproximateMaxLength, limit, trimMode, flags); + + public Task StreamAcknowledgeAsync(RedisKey key, RedisValue groupName, RedisValue messageId, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAcknowledgeAsync(key, groupName, messageId, flags); + + public Task StreamAcknowledgeAsync(RedisKey key, RedisValue groupName, RedisValue[] messageIds, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAcknowledgeAsync(key, groupName, messageIds, flags); + + public Task StreamAcknowledgeAndDeleteAsync(RedisKey key, RedisValue groupName, StreamTrimMode mode, RedisValue messageId, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAcknowledgeAndDeleteAsync(key, groupName, mode, messageId, flags); + + public Task StreamAcknowledgeAndDeleteAsync(RedisKey key, RedisValue groupName, StreamTrimMode mode, RedisValue[] messageIds, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAcknowledgeAndDeleteAsync(key, groupName, mode, messageIds, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Streams.cs b/src/StackExchange.Redis/MultiGroupDatabase.Streams.cs new file mode 100644 index 000000000..e81e88f75 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Streams.cs @@ -0,0 +1,121 @@ +using System; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // Stream operations + public StreamAutoClaimIdsOnlyResult StreamAutoClaimIdsOnly(RedisKey key, RedisValue consumerGroup, RedisValue claimingConsumer, long minIdleTimeInMs, RedisValue startAtId, int? count = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAutoClaimIdsOnly(key, consumerGroup, claimingConsumer, minIdleTimeInMs, startAtId, count, flags); + + public StreamAutoClaimResult StreamAutoClaim(RedisKey key, RedisValue consumerGroup, RedisValue claimingConsumer, long minIdleTimeInMs, RedisValue startAtId, int? count = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAutoClaim(key, consumerGroup, claimingConsumer, minIdleTimeInMs, startAtId, count, flags); + + public RedisValue StreamAdd(RedisKey key, RedisValue streamField, RedisValue streamValue, RedisValue? messageId = null, int? maxLength = null, bool useApproximateMaxLength = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAdd(key, streamField, streamValue, messageId, maxLength, useApproximateMaxLength, flags); + + public RedisValue StreamAdd(RedisKey key, RedisValue streamField, RedisValue streamValue, RedisValue? messageId = null, long? maxLength = null, bool useApproximateMaxLength = false, long? limit = null, StreamTrimMode trimMode = StreamTrimMode.KeepReferences, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAdd(key, streamField, streamValue, messageId, maxLength, useApproximateMaxLength, limit, trimMode, flags); + + public RedisValue StreamAdd(RedisKey key, NameValueEntry[] streamPairs, RedisValue? messageId = null, int? maxLength = null, bool useApproximateMaxLength = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAdd(key, streamPairs, messageId, maxLength, useApproximateMaxLength, flags); + + public RedisValue StreamAdd(RedisKey key, NameValueEntry[] streamPairs, RedisValue? messageId = null, long? maxLength = null, bool useApproximateMaxLength = false, long? limit = null, StreamTrimMode trimMode = StreamTrimMode.KeepReferences, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAdd(key, streamPairs, messageId, maxLength, useApproximateMaxLength, limit, trimMode, flags); + + public StreamEntry[] StreamClaim(RedisKey key, RedisValue consumerGroup, RedisValue claimingConsumer, long minIdleTimeInMs, RedisValue[] messageIds, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamClaim(key, consumerGroup, claimingConsumer, minIdleTimeInMs, messageIds, flags); + + public RedisValue[] StreamClaimIdsOnly(RedisKey key, RedisValue consumerGroup, RedisValue claimingConsumer, long minIdleTimeInMs, RedisValue[] messageIds, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamClaimIdsOnly(key, consumerGroup, claimingConsumer, minIdleTimeInMs, messageIds, flags); + + public bool StreamConsumerGroupSetPosition(RedisKey key, RedisValue groupName, RedisValue position, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamConsumerGroupSetPosition(key, groupName, position, flags); + + public StreamConsumerInfo[] StreamConsumerInfo(RedisKey key, RedisValue groupName, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamConsumerInfo(key, groupName, flags); + + public bool StreamCreateConsumerGroup(RedisKey key, RedisValue groupName, RedisValue? position, CommandFlags flags) + => GetDatabase().StreamCreateConsumerGroup(key, groupName, position, flags); + + public bool StreamCreateConsumerGroup(RedisKey key, RedisValue groupName, RedisValue? position = null, bool createStream = true, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamCreateConsumerGroup(key, groupName, position, createStream, flags); + + public long StreamDelete(RedisKey key, RedisValue[] messageIds, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamDelete(key, messageIds, flags); + + public long StreamDeleteConsumer(RedisKey key, RedisValue groupName, RedisValue consumerName, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamDeleteConsumer(key, groupName, consumerName, flags); + + public bool StreamDeleteConsumerGroup(RedisKey key, RedisValue groupName, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamDeleteConsumerGroup(key, groupName, flags); + + public StreamGroupInfo[] StreamGroupInfo(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamGroupInfo(key, flags); + + public StreamInfo StreamInfo(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamInfo(key, flags); + + public long StreamLength(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamLength(key, flags); + + public StreamPendingInfo StreamPending(RedisKey key, RedisValue groupName, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamPending(key, groupName, flags); + + public StreamPendingMessageInfo[] StreamPendingMessages(RedisKey key, RedisValue groupName, int count, RedisValue consumerName, RedisValue? minId = null, RedisValue? maxId = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamPendingMessages(key, groupName, count, consumerName, minId, maxId, flags); + + public StreamEntry[] StreamRange(RedisKey key, RedisValue? minId = null, RedisValue? maxId = null, int? count = null, Order messageOrder = Order.Ascending, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamRange(key, minId, maxId, count, messageOrder, flags); + + public StreamEntry[] StreamRead(RedisKey key, RedisValue position, int? count = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamRead(key, position, count, flags); + + public RedisStream[] StreamRead(StreamPosition[] streamPositions, int? countPerStream = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamRead(streamPositions, countPerStream, flags); + + public StreamEntry[] StreamReadGroup(RedisKey key, RedisValue groupName, RedisValue consumerName, RedisValue? position, int? count, CommandFlags flags) + => GetDatabase().StreamReadGroup(key, groupName, consumerName, position, count, flags); + + public StreamEntry[] StreamReadGroup(RedisKey key, RedisValue groupName, RedisValue consumerName, RedisValue? position = null, int? count = null, bool noAck = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamReadGroup(key, groupName, consumerName, position, count, noAck, flags); + + public RedisStream[] StreamReadGroup(StreamPosition[] streamPositions, RedisValue groupName, RedisValue consumerName, int? countPerStream, CommandFlags flags) + => GetDatabase().StreamReadGroup(streamPositions, groupName, consumerName, countPerStream, flags); + + public RedisStream[] StreamReadGroup(StreamPosition[] streamPositions, RedisValue groupName, RedisValue consumerName, int? countPerStream = null, bool noAck = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamReadGroup(streamPositions, groupName, consumerName, countPerStream, noAck, flags); + + public long StreamTrim(RedisKey key, int maxLength, bool useApproximateMaxLength = false, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamTrim(key, maxLength, useApproximateMaxLength, flags); + + public long StreamAcknowledge(RedisKey key, RedisValue groupName, RedisValue messageId, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAcknowledge(key, groupName, messageId, flags); + + public long StreamAcknowledge(RedisKey key, RedisValue groupName, RedisValue[] messageIds, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAcknowledge(key, groupName, messageIds, flags); + + public StreamTrimResult StreamAcknowledgeAndDelete(RedisKey key, RedisValue groupName, StreamTrimMode mode, RedisValue messageId, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAcknowledgeAndDelete(key, groupName, mode, messageId, flags); + + public StreamTrimResult[] StreamAcknowledgeAndDelete(RedisKey key, RedisValue groupName, StreamTrimMode mode, RedisValue[] messageIds, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamAcknowledgeAndDelete(key, groupName, mode, messageIds, flags); + + public StreamTrimResult[] StreamDelete(RedisKey key, RedisValue[] messageIds, StreamTrimMode mode, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamDelete(key, messageIds, mode, flags); + + public StreamPendingMessageInfo[] StreamPendingMessages(RedisKey key, RedisValue groupName, int count, RedisValue consumerName, RedisValue? minId = null, RedisValue? maxId = null, long? idle = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamPendingMessages(key, groupName, count, consumerName, minId, maxId, idle, flags); + + public StreamEntry[] StreamReadGroup(RedisKey key, RedisValue groupName, RedisValue consumerName, RedisValue? position = null, int? count = null, bool noAck = false, TimeSpan? blockingTimeout = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamReadGroup(key, groupName, consumerName, position, count, noAck, blockingTimeout, flags); + + public RedisStream[] StreamReadGroup(StreamPosition[] streamPositions, RedisValue groupName, RedisValue consumerName, int? countPerStream = null, bool noAck = false, TimeSpan? blockingTimeout = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamReadGroup(streamPositions, groupName, consumerName, countPerStream, noAck, blockingTimeout, flags); + + public long StreamTrim(RedisKey key, long maxLength, bool useApproximateMaxLength = false, long? limit = null, StreamTrimMode trimMode = StreamTrimMode.KeepReferences, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamTrim(key, maxLength, useApproximateMaxLength, limit, trimMode, flags); + + public long StreamTrimByMinId(RedisKey key, RedisValue minId, bool useApproximateMaxLength = false, long? limit = null, StreamTrimMode trimMode = StreamTrimMode.KeepReferences, CommandFlags flags = CommandFlags.None) + => GetDatabase().StreamTrimByMinId(key, minId, useApproximateMaxLength, limit, trimMode, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Strings.Async.cs b/src/StackExchange.Redis/MultiGroupDatabase.Strings.Async.cs new file mode 100644 index 000000000..e98c15fcb --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Strings.Async.cs @@ -0,0 +1,119 @@ +using System; +using System.Threading.Tasks; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // String Async operations + public Task StringAppendAsync(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringAppendAsync(key, value, flags); + + public Task StringBitCountAsync(RedisKey key, long start, long end, CommandFlags flags) + => GetDatabase().StringBitCountAsync(key, start, end, flags); + + public Task StringBitCountAsync(RedisKey key, long start = 0, long end = -1, StringIndexType indexType = StringIndexType.Byte, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringBitCountAsync(key, start, end, indexType, flags); + + public Task StringBitOperationAsync(Bitwise operation, RedisKey destination, RedisKey first, RedisKey second = default, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringBitOperationAsync(operation, destination, first, second, flags); + + public Task StringBitOperationAsync(Bitwise operation, RedisKey destination, RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringBitOperationAsync(operation, destination, keys, flags); + + public Task StringBitPositionAsync(RedisKey key, bool bit, long start, long end, CommandFlags flags) + => GetDatabase().StringBitPositionAsync(key, bit, start, end, flags); + + public Task StringBitPositionAsync(RedisKey key, bool bit, long start = 0, long end = -1, StringIndexType indexType = StringIndexType.Byte, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringBitPositionAsync(key, bit, start, end, indexType, flags); + + public Task StringDecrementAsync(RedisKey key, long value = 1, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringDecrementAsync(key, value, flags); + + public Task StringDecrementAsync(RedisKey key, double value, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringDecrementAsync(key, value, flags); + + public Task StringDeleteAsync(RedisKey key, ValueCondition when, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringDeleteAsync(key, when, flags); + + public Task StringDigestAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringDigestAsync(key, flags); + + public Task StringGetAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetAsync(key, flags); + + public Task StringGetAsync(RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetAsync(keys, flags); + + public Task?> StringGetLeaseAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetLeaseAsync(key, flags); + + public Task StringGetBitAsync(RedisKey key, long offset, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetBitAsync(key, offset, flags); + + public Task StringGetRangeAsync(RedisKey key, long start, long end, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetRangeAsync(key, start, end, flags); + + public Task StringGetSetAsync(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetSetAsync(key, value, flags); + + public Task StringGetSetExpiryAsync(RedisKey key, TimeSpan? expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetSetExpiryAsync(key, expiry, flags); + + public Task StringGetSetExpiryAsync(RedisKey key, DateTime expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetSetExpiryAsync(key, expiry, flags); + + public Task StringGetDeleteAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetDeleteAsync(key, flags); + + public Task StringGetWithExpiryAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetWithExpiryAsync(key, flags); + + public Task StringIncrementAsync(RedisKey key, long value = 1, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringIncrementAsync(key, value, flags); + + public Task StringIncrementAsync(RedisKey key, double value, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringIncrementAsync(key, value, flags); + + public Task StringLengthAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringLengthAsync(key, flags); + + public Task StringLongestCommonSubsequenceAsync(RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringLongestCommonSubsequenceAsync(first, second, flags); + + public Task StringLongestCommonSubsequenceLengthAsync(RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringLongestCommonSubsequenceLengthAsync(first, second, flags); + + public Task StringLongestCommonSubsequenceWithMatchesAsync(RedisKey first, RedisKey second, long minLength = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringLongestCommonSubsequenceWithMatchesAsync(first, second, minLength, flags); + + public Task StringSetAsync(RedisKey key, RedisValue value, TimeSpan? expiry, When when) + => GetDatabase().StringSetAsync(key, value, expiry, when); + + public Task StringSetAsync(RedisKey key, RedisValue value, TimeSpan? expiry, When when, CommandFlags flags) + => GetDatabase().StringSetAsync(key, value, expiry, when, flags); + + public Task StringSetAsync(RedisKey key, RedisValue value, TimeSpan? expiry, bool keepTtl, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringSetAsync(key, value, expiry, keepTtl, when, flags); + + public Task StringSetAsync(RedisKey key, RedisValue value, Expiration expiry = default, ValueCondition when = default, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringSetAsync(key, value, expiry, when, flags); + + public Task StringSetAsync(System.Collections.Generic.KeyValuePair[] values, When when, CommandFlags flags) + => GetDatabase().StringSetAsync(values, when, flags); + + public Task StringSetAsync(System.Collections.Generic.KeyValuePair[] values, When when = When.Always, Expiration expiry = default, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringSetAsync(values, when, expiry, flags); + + public Task StringSetAndGetAsync(RedisKey key, RedisValue value, TimeSpan? expiry, When when, CommandFlags flags) + => GetDatabase().StringSetAndGetAsync(key, value, expiry, when, flags); + + public Task StringSetAndGetAsync(RedisKey key, RedisValue value, TimeSpan? expiry = null, bool keepTtl = false, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringSetAndGetAsync(key, value, expiry, keepTtl, when, flags); + + public Task StringSetBitAsync(RedisKey key, long offset, bool bit, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringSetBitAsync(key, offset, bit, flags); + + public Task StringSetRangeAsync(RedisKey key, long offset, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringSetRangeAsync(key, offset, value, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.Strings.cs b/src/StackExchange.Redis/MultiGroupDatabase.Strings.cs new file mode 100644 index 000000000..08813b215 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.Strings.cs @@ -0,0 +1,118 @@ +using System; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // String operations + public long StringAppend(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringAppend(key, value, flags); + + public long StringBitCount(RedisKey key, long start, long end, CommandFlags flags) + => GetDatabase().StringBitCount(key, start, end, flags); + + public long StringBitCount(RedisKey key, long start = 0, long end = -1, StringIndexType indexType = StringIndexType.Byte, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringBitCount(key, start, end, indexType, flags); + + public long StringBitOperation(Bitwise operation, RedisKey destination, RedisKey first, RedisKey second = default, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringBitOperation(operation, destination, first, second, flags); + + public long StringBitOperation(Bitwise operation, RedisKey destination, RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringBitOperation(operation, destination, keys, flags); + + public long StringBitPosition(RedisKey key, bool bit, long start, long end, CommandFlags flags) + => GetDatabase().StringBitPosition(key, bit, start, end, flags); + + public long StringBitPosition(RedisKey key, bool bit, long start = 0, long end = -1, StringIndexType indexType = StringIndexType.Byte, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringBitPosition(key, bit, start, end, indexType, flags); + + public long StringDecrement(RedisKey key, long value = 1, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringDecrement(key, value, flags); + + public double StringDecrement(RedisKey key, double value, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringDecrement(key, value, flags); + + public bool StringDelete(RedisKey key, ValueCondition when, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringDelete(key, when, flags); + + public ValueCondition? StringDigest(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringDigest(key, flags); + + public RedisValue StringGet(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGet(key, flags); + + public RedisValue[] StringGet(RedisKey[] keys, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGet(keys, flags); + + public Lease? StringGetLease(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetLease(key, flags); + + public bool StringGetBit(RedisKey key, long offset, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetBit(key, offset, flags); + + public RedisValue StringGetRange(RedisKey key, long start, long end, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetRange(key, start, end, flags); + + public RedisValue StringGetSet(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetSet(key, value, flags); + + public RedisValue StringGetSetExpiry(RedisKey key, TimeSpan? expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetSetExpiry(key, expiry, flags); + + public RedisValue StringGetSetExpiry(RedisKey key, DateTime expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetSetExpiry(key, expiry, flags); + + public RedisValue StringGetDelete(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetDelete(key, flags); + + public RedisValueWithExpiry StringGetWithExpiry(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringGetWithExpiry(key, flags); + + public long StringIncrement(RedisKey key, long value = 1, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringIncrement(key, value, flags); + + public double StringIncrement(RedisKey key, double value, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringIncrement(key, value, flags); + + public long StringLength(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringLength(key, flags); + + public string? StringLongestCommonSubsequence(RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringLongestCommonSubsequence(first, second, flags); + + public long StringLongestCommonSubsequenceLength(RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringLongestCommonSubsequenceLength(first, second, flags); + + public LCSMatchResult StringLongestCommonSubsequenceWithMatches(RedisKey first, RedisKey second, long minLength = 0, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringLongestCommonSubsequenceWithMatches(first, second, minLength, flags); + + public bool StringSet(RedisKey key, RedisValue value, TimeSpan? expiry, When when) + => GetDatabase().StringSet(key, value, expiry, when); + + public bool StringSet(RedisKey key, RedisValue value, TimeSpan? expiry, When when, CommandFlags flags) + => GetDatabase().StringSet(key, value, expiry, when, flags); + + public bool StringSet(RedisKey key, RedisValue value, TimeSpan? expiry, bool keepTtl, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringSet(key, value, expiry, keepTtl, when, flags); + + public bool StringSet(RedisKey key, RedisValue value, Expiration expiry = default, ValueCondition when = default, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringSet(key, value, expiry, when, flags); + + public bool StringSet(System.Collections.Generic.KeyValuePair[] values, When when, CommandFlags flags) + => GetDatabase().StringSet(values, when, flags); + + public bool StringSet(System.Collections.Generic.KeyValuePair[] values, When when = When.Always, Expiration expiry = default, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringSet(values, when, expiry, flags); + + public RedisValue StringSetAndGet(RedisKey key, RedisValue value, TimeSpan? expiry, When when, CommandFlags flags) + => GetDatabase().StringSetAndGet(key, value, expiry, when, flags); + + public RedisValue StringSetAndGet(RedisKey key, RedisValue value, TimeSpan? expiry = null, bool keepTtl = false, When when = When.Always, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringSetAndGet(key, value, expiry, keepTtl, when, flags); + + public bool StringSetBit(RedisKey key, long offset, bool bit, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringSetBit(key, offset, bit, flags); + + public RedisValue StringSetRange(RedisKey key, long offset, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().StringSetRange(key, offset, value, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.VectorSets.Async.cs b/src/StackExchange.Redis/MultiGroupDatabase.VectorSets.Async.cs new file mode 100644 index 000000000..f7960ad60 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.VectorSets.Async.cs @@ -0,0 +1,49 @@ +using System.Threading.Tasks; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // VectorSet Async operations + public Task VectorSetAddAsync(RedisKey key, VectorSetAddRequest request, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetAddAsync(key, request, flags); + + public Task VectorSetLengthAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetLengthAsync(key, flags); + + public Task VectorSetDimensionAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetDimensionAsync(key, flags); + + public Task?> VectorSetGetApproximateVectorAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetGetApproximateVectorAsync(key, member, flags); + + public Task VectorSetGetAttributesJsonAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetGetAttributesJsonAsync(key, member, flags); + + public Task VectorSetInfoAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetInfoAsync(key, flags); + + public Task VectorSetContainsAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetContainsAsync(key, member, flags); + + public Task?> VectorSetGetLinksAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetGetLinksAsync(key, member, flags); + + public Task?> VectorSetGetLinksWithScoresAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetGetLinksWithScoresAsync(key, member, flags); + + public Task VectorSetRandomMemberAsync(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetRandomMemberAsync(key, flags); + + public Task VectorSetRandomMembersAsync(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetRandomMembersAsync(key, count, flags); + + public Task VectorSetRemoveAsync(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetRemoveAsync(key, member, flags); + + public Task VectorSetSetAttributesJsonAsync(RedisKey key, RedisValue member, string attributesJson, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetSetAttributesJsonAsync(key, member, attributesJson, flags); + + public Task?> VectorSetSimilaritySearchAsync(RedisKey key, VectorSetSimilaritySearchRequest query, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetSimilaritySearchAsync(key, query, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.VectorSets.cs b/src/StackExchange.Redis/MultiGroupDatabase.VectorSets.cs new file mode 100644 index 000000000..4d7d7425c --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.VectorSets.cs @@ -0,0 +1,47 @@ +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase +{ + // VectorSet operations + public bool VectorSetAdd(RedisKey key, VectorSetAddRequest request, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetAdd(key, request, flags); + + public long VectorSetLength(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetLength(key, flags); + + public int VectorSetDimension(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetDimension(key, flags); + + public Lease? VectorSetGetApproximateVector(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetGetApproximateVector(key, member, flags); + + public string? VectorSetGetAttributesJson(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetGetAttributesJson(key, member, flags); + + public VectorSetInfo? VectorSetInfo(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetInfo(key, flags); + + public bool VectorSetContains(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetContains(key, member, flags); + + public Lease? VectorSetGetLinks(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetGetLinks(key, member, flags); + + public Lease? VectorSetGetLinksWithScores(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetGetLinksWithScores(key, member, flags); + + public RedisValue VectorSetRandomMember(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetRandomMember(key, flags); + + public RedisValue[] VectorSetRandomMembers(RedisKey key, long count, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetRandomMembers(key, count, flags); + + public bool VectorSetRemove(RedisKey key, RedisValue member, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetRemove(key, member, flags); + + public bool VectorSetSetAttributesJson(RedisKey key, RedisValue member, string attributesJson, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetSetAttributesJson(key, member, attributesJson, flags); + + public Lease? VectorSetSimilaritySearch(RedisKey key, VectorSetSimilaritySearchRequest query, CommandFlags flags = CommandFlags.None) + => GetDatabase().VectorSetSimilaritySearch(key, query, flags); +} diff --git a/src/StackExchange.Redis/MultiGroupDatabase.cs b/src/StackExchange.Redis/MultiGroupDatabase.cs new file mode 100644 index 000000000..10aa11ac0 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupDatabase.cs @@ -0,0 +1,105 @@ +using System; + +namespace StackExchange.Redis; + +internal sealed partial class MultiGroupDatabase : IDatabase +{ + private readonly MultiGroupMultiplexer _parent; + private readonly int _database; + private readonly object? _asyncState; + + public MultiGroupDatabase(MultiGroupMultiplexer parent, int database, object? asyncState) + { + _parent = parent; + _database = database; + _asyncState = asyncState; + } + + public object? AsyncState => _asyncState; + public int Database => _database < 0 ? GetDatabase().Database : _database; + + public IConnectionMultiplexer Multiplexer => _parent; + + // for high DB numbers this might allocate even for null async-state scenarios; unavoidable for now + private IDatabase GetDatabase() => _parent.Active.GetDatabase(_database, _asyncState); + + // Core methods + public IBatch CreateBatch(object? asyncState = null) + => GetDatabase().CreateBatch(asyncState); + + public ITransaction CreateTransaction(object? asyncState = null) + => GetDatabase().CreateTransaction(asyncState); + + public void KeyMigrate(RedisKey key, System.Net.EndPoint toServer, int toDatabase = 0, int timeoutMilliseconds = 0, MigrateOptions migrateOptions = MigrateOptions.None, CommandFlags flags = CommandFlags.None) + => GetDatabase().KeyMigrate(key, toServer, toDatabase, timeoutMilliseconds, migrateOptions, flags); + + public RedisValue DebugObject(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().DebugObject(key, flags); + + public System.Net.EndPoint? IdentifyEndpoint(RedisKey key = default, CommandFlags flags = CommandFlags.None) + => GetDatabase().IdentifyEndpoint(key, flags); + + public bool IsConnected(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().IsConnected(key, flags); + + public System.TimeSpan Ping(CommandFlags flags = CommandFlags.None) + => GetDatabase().Ping(flags); + + public long Publish(RedisChannel channel, RedisValue message, CommandFlags flags = CommandFlags.None) + => GetDatabase().Publish(channel, message, flags); + + public RedisResult Execute(string command, params object[] args) + => GetDatabase().Execute(command, args); + + public RedisResult Execute(string command, System.Collections.Generic.ICollection args, CommandFlags flags = CommandFlags.None) + => GetDatabase().Execute(command, args, flags); + + public RedisResult ScriptEvaluate(string script, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().ScriptEvaluate(script, keys, values, flags); + + public RedisResult ScriptEvaluate(byte[] hash, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().ScriptEvaluate(hash, keys, values, flags); + + public RedisResult ScriptEvaluate(LuaScript script, object? parameters = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().ScriptEvaluate(script, parameters, flags); + + public RedisResult ScriptEvaluate(LoadedLuaScript script, object? parameters = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().ScriptEvaluate(script, parameters, flags); + + public RedisResult ScriptEvaluateReadOnly(string script, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().ScriptEvaluateReadOnly(script, keys, values, flags); + + public RedisResult ScriptEvaluateReadOnly(byte[] hash, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().ScriptEvaluateReadOnly(hash, keys, values, flags); + + public bool LockExtend(RedisKey key, RedisValue value, TimeSpan expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().LockExtend(key, value, expiry, flags); + + public RedisValue LockQuery(RedisKey key, CommandFlags flags = CommandFlags.None) + => GetDatabase().LockQuery(key, flags); + + public bool LockRelease(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) + => GetDatabase().LockRelease(key, value, flags); + + public bool LockTake(RedisKey key, RedisValue value, TimeSpan expiry, CommandFlags flags = CommandFlags.None) + => GetDatabase().LockTake(key, value, expiry, flags); + + public RedisValue[] Sort(RedisKey key, long skip = 0, long take = -1, Order order = Order.Ascending, SortType sortType = SortType.Numeric, RedisValue by = default, RedisValue[]? get = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().Sort(key, skip, take, order, sortType, by, get, flags); + + public long SortAndStore(RedisKey destination, RedisKey key, long skip = 0, long take = -1, Order order = Order.Ascending, SortType sortType = SortType.Numeric, RedisValue by = default, RedisValue[]? get = null, CommandFlags flags = CommandFlags.None) + => GetDatabase().SortAndStore(destination, key, skip, take, order, sortType, by, get, flags); + + // IRedisAsync methods + public bool TryWait(System.Threading.Tasks.Task task) + => GetDatabase().TryWait(task); + + public void Wait(System.Threading.Tasks.Task task) + => GetDatabase().Wait(task); + + public T Wait(System.Threading.Tasks.Task task) + => GetDatabase().Wait(task); + + public void WaitAll(params System.Threading.Tasks.Task[] tasks) + => GetDatabase().WaitAll(tasks); +} diff --git a/src/StackExchange.Redis/MultiGroupMultiplexer.cs b/src/StackExchange.Redis/MultiGroupMultiplexer.cs new file mode 100644 index 000000000..ab5286230 --- /dev/null +++ b/src/StackExchange.Redis/MultiGroupMultiplexer.cs @@ -0,0 +1,432 @@ +using System; +using System.Buffers; +using System.Diagnostics; +using System.IO; +using System.Net; +using System.Threading.Tasks; +using StackExchange.Redis.Maintenance; +using StackExchange.Redis.Profiling; + +namespace StackExchange.Redis; + +internal sealed class MultiGroupMultiplexer : IConnectionMultiplexer +{ + private ConnectionMultiplexer[] _muxers; + + private ConnectionMultiplexer? _active; + + public override string ToString() => _active is { } active ? active.ToString() : "No active connection"; + + internal ConnectionMultiplexer Active + { + get + { + return _active ?? Throw(); + static ConnectionMultiplexer Throw() => throw new ObjectDisposedException("All connections are unavailable."); + } + } + + internal static async Task ConnectAsync(ConfigurationOptions[] configs, TextWriter? log) + { + var pending = new Task[configs.Length]; + for (int i = 0; i < configs.Length; i++) + { + var config = configs[i]; + config.AbortOnConnectFail = false; + pending[i] = ConnectionMultiplexer.ConnectAsync(config, log); + } + ConnectionMultiplexer[] muxers = new ConnectionMultiplexer[pending.Length]; + for (int i = 0; i < pending.Length; i++) + { + muxers[i] = await pending[i].ConfigureAwait(false); + } + return new MultiGroupMultiplexer(muxers); + } + private MultiGroupMultiplexer(ConnectionMultiplexer[] muxers) + { + _muxers = muxers; + if (muxers.Length == 0) throw new ArgumentException("No muxers specified"); + _active = null; + SelectPreferredGroup(); + } + + private void SelectPreferredGroup() + { + var arr = _muxers; + var weights = ArrayPool.Shared.Rent(arr.Length); + var indices = ArrayPool.Shared.Rent(arr.Length); + for (int i = 0; i < arr.Length; i++) + { + var grp = arr[i]; + weights[i] = new GroupWeight(grp.RawConfig.Weight, grp.LatencyTicks); + indices[i] = i; + } + Array.Sort(weights, indices, 0, arr.Length); + for (int i = 0; i < arr.Length; i++) + { + var muxer = arr[indices[i]]; + if (muxer.IsConnected) + { + _active = muxer; + break; + } + } + + ArrayPool.Shared.Return(weights); + ArrayPool.Shared.Return(indices); + } + + private readonly struct GroupWeight(float weight, int latency) : IComparable + { + public readonly float Weight = weight; + public readonly int Latency = latency; + + public int CompareTo(GroupWeight other) + { + var delta = this.Weight.CompareTo(other.Weight); + return delta != 0 ? delta : this.Latency.CompareTo(other.Latency); + } + } + + public void Dispose() => throw new NotImplementedException(); + + public ValueTask DisposeAsync() => throw new NotImplementedException(); + + public string ClientName => Active.ClientName; + public string Configuration => Active.Configuration; + public int TimeoutMilliseconds => Active.TimeoutMilliseconds; + + public long OperationCount + { + get + { + long count = 0; + foreach (var muxer in _muxers) + { + count += muxer.OperationCount; + } + return count; + } + } + + [Obsolete] + public bool PreserveAsyncOrder + { + get => Active.PreserveAsyncOrder; + set => Active.PreserveAsyncOrder = value; + } + + public bool IsConnected => Active.IsConnected; + public bool IsConnecting => Active.IsConnecting; + + [Obsolete] + public bool IncludeDetailInExceptions + { + get => Active.IncludeDetailInExceptions; + set => Active.IncludeDetailInExceptions = value; + } + + public int StormLogThreshold + { + get => Active.StormLogThreshold; + set => Active.StormLogThreshold = value; + } + + public void RegisterProfiler(Func profilingSessionProvider) + { + foreach (var muxer in _muxers) + { + muxer.RegisterProfiler(profilingSessionProvider); + } + } + + public ServerCounters GetCounters() => Active.GetCounters(); + + public event EventHandler? ErrorMessage + { + add + { + foreach (var muxer in _muxers) + { + muxer.ErrorMessage += value; + } + } + remove + { + foreach (var muxer in _muxers) + { + muxer.ErrorMessage -= value; + } + } + } + public event EventHandler? ConnectionFailed + { + add + { + foreach (var muxer in _muxers) + { + muxer.ConnectionFailed += value; + } + } + remove + { + foreach (var muxer in _muxers) + { + muxer.ConnectionFailed -= value; + } + } + } + public event EventHandler? InternalError + { + add + { + foreach (var muxer in _muxers) + { + muxer.InternalError += value; + } + } + remove + { + foreach (var muxer in _muxers) + { + muxer.InternalError -= value; + } + } + } + public event EventHandler? ConnectionRestored + { + add + { + foreach (var muxer in _muxers) + { + muxer.ConnectionRestored += value; + } + } + remove + { + foreach (var muxer in _muxers) + { + muxer.ConnectionRestored -= value; + } + } + } + public event EventHandler? ConfigurationChanged + { + add + { + foreach (var muxer in _muxers) + { + muxer.ConfigurationChanged += value; + } + } + remove + { + foreach (var muxer in _muxers) + { + muxer.ConfigurationChanged -= value; + } + } + } + public event EventHandler? ConfigurationChangedBroadcast + { + add + { + foreach (var muxer in _muxers) + { + muxer.ConfigurationChangedBroadcast += value; + } + } + remove + { + foreach (var muxer in _muxers) + { + muxer.ConfigurationChangedBroadcast -= value; + } + } + } + public event EventHandler? ServerMaintenanceEvent + { + add + { + foreach (var muxer in _muxers) + { + muxer.ServerMaintenanceEvent += value; + } + } + remove + { + foreach (var muxer in _muxers) + { + muxer.ServerMaintenanceEvent -= value; + } + } + } + public EndPoint[] GetEndPoints(bool configuredOnly = false) => Active.GetEndPoints(configuredOnly); + + public void Wait(Task task) => Active.Wait(task); + + public T Wait(Task task) => Active.Wait(task); + + public void WaitAll(params Task[] tasks) => Active.WaitAll(tasks); + + public event EventHandler? HashSlotMoved + { + add + { + foreach (var muxer in _muxers) + { + muxer.HashSlotMoved += value; + } + } + remove + { + foreach (var muxer in _muxers) + { + muxer.HashSlotMoved -= value; + } + } + } + + public int HashSlot(RedisKey key) => Active.HashSlot(key); + + public ISubscriber GetSubscriber(object? asyncState = null) => throw new NotImplementedException(); + + public IDatabase GetDatabase(int db = -1, object? asyncState = null) + { + if (asyncState is null & db >= -1 & db <= ConnectionMultiplexer.MaxCachedDatabaseInstance) + { + return _databases[db + 1] ??= new MultiGroupDatabase(this, db, null); + } + return new MultiGroupDatabase(this, db, asyncState); + } + + private readonly IDatabase?[] _databases = new IDatabase?[ConnectionMultiplexer.MaxCachedDatabaseInstance + 2]; + + public IServer GetServer(string host, int port, object? asyncState = null) + { + Exception ex; + try + { + // try "active" first, and preserve the exception + return Active.GetServer(host, port, asyncState); + } + catch (Exception e) + { + ex = e; + } + foreach (var muxer in _muxers) + { + try + { + return muxer.GetServer(host, port, asyncState); + } + catch (Exception e) { Debug.WriteLine(e.Message); } + } + throw ex; + } + + public IServer GetServer(string hostAndPort, object? asyncState = null) + { + Exception ex; + try + { + // try "active" first, and preserve the exception + return Active.GetServer(hostAndPort, asyncState); + } + catch (Exception e) + { + ex = e; + } + foreach (var muxer in _muxers) + { + try + { + return muxer.GetServer(hostAndPort, asyncState); + } + catch (Exception e) { Debug.WriteLine(e.Message); } + } + throw ex; + } + + public IServer GetServer(IPAddress host, int port) + { + Exception ex; + try + { + // try "active" first, and preserve the exception + return Active.GetServer(host, port); + } + catch (Exception e) + { + ex = e; + } + foreach (var muxer in _muxers) + { + try + { + return muxer.GetServer(host, port); + } + catch (Exception e) { Debug.WriteLine(e.Message); } + } + throw ex; + } + + public IServer GetServer(EndPoint endpoint, object? asyncState = null) + { + Exception ex; + try + { + // try "active" first, and preserve the exception + return Active.GetServer(endpoint, asyncState); + } + catch (Exception e) + { + ex = e; + } + foreach (var muxer in _muxers) + { + try + { + return muxer.GetServer(endpoint, asyncState); + } + catch (Exception e) { Debug.WriteLine(e.Message); } + } + throw ex; + } + + public IServer GetServer(RedisKey key, object? asyncState = null, CommandFlags flags = CommandFlags.None) => Active.GetServer(key, asyncState, flags); + + public IServer[] GetServers() => Active.GetServers(); + + public Task ConfigureAsync(TextWriter? log = null) => Active.ConfigureAsync(log); + + public bool Configure(TextWriter? log = null) => Active.Configure(log); + + public string GetStatus() => Active.GetStatus(); + + public void GetStatus(TextWriter log) => Active.GetStatus(log); + + public void Close(bool allowCommandsToComplete = true) => Active.Close(allowCommandsToComplete); + + public Task CloseAsync(bool allowCommandsToComplete = true) => Active.CloseAsync(allowCommandsToComplete); + + public string? GetStormLog() => Active.GetStormLog(); + + public void ResetStormLog() => Active.ResetStormLog(); + + public long PublishReconfigure(CommandFlags flags = CommandFlags.None) => Active.PublishReconfigure(flags); + + public Task PublishReconfigureAsync(CommandFlags flags = CommandFlags.None) => Active.PublishReconfigureAsync(flags); + + public int GetHashSlot(RedisKey key) => Active.GetHashSlot(key); + + public void ExportConfiguration(Stream destination, ExportOptions options = ExportOptions.All) => Active.ExportConfiguration(destination, options); + + public void AddLibraryNameSuffix(string suffix) + { + foreach (var muxer in _muxers) + { + muxer.AddLibraryNameSuffix(suffix); + } + } +} diff --git a/src/StackExchange.Redis/PublicAPI/PublicAPI.Unshipped.txt b/src/StackExchange.Redis/PublicAPI/PublicAPI.Unshipped.txt index 91b0e1a43..0c9d9d46f 100644 --- a/src/StackExchange.Redis/PublicAPI/PublicAPI.Unshipped.txt +++ b/src/StackExchange.Redis/PublicAPI/PublicAPI.Unshipped.txt @@ -1 +1,3 @@ -#nullable enable \ No newline at end of file +#nullable enable +StackExchange.Redis.ConfigurationOptions.Weight.get -> float +StackExchange.Redis.ConfigurationOptions.Weight.set -> void \ No newline at end of file diff --git a/src/StackExchange.Redis/StackExchange.Redis.csproj b/src/StackExchange.Redis/StackExchange.Redis.csproj index 983624bc0..47211d45e 100644 --- a/src/StackExchange.Redis/StackExchange.Redis.csproj +++ b/src/StackExchange.Redis/StackExchange.Redis.csproj @@ -51,4 +51,10 @@ + + + + MultiGroupDatabase.cs + + \ No newline at end of file