Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support SMISMEMBER #2077

Merged
merged 15 commits into from
Apr 12, 2022
3 changes: 2 additions & 1 deletion docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Note: does *not* increment a major version (as these are warnings to consumers), because: they're warnings (errors are opt-in), removing obsolete types with a 3.0 rev _would_ be binary breaking (this isn't), and reving to 3.0 would cause binding redirect pain for consumers. Bumping from 2.5 to 2.6 only for this change.
- Adds: Support for `COPY` with `.KeyCopy()`/`.KeyCopyAsync()` ([#2064 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2064))
- Adds: Support for `LMOVE` with `.ListMove()`/`.ListMoveAsync()` ([#2065 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2065))
- Adds: Support for `SMISMEMBER` with `.SetContains()`/`.SetContainsAsync()` ([#2077 by Avital-Fine](https://github.com/StackExchange/StackExchange.Redis/pull/2077))

## 2.5.61

Expand All @@ -25,7 +26,7 @@

## 2.5.43

- Adds: Bounds checking for `ExponentialRetry` backoff policy ([#1921 by gliljas](https://github.com/StackExchange/StackExchange.Redis/pull/1921))
- Adds: Bounds checking for `ExponentialRetry` backoff policy ([#1921 by gliljas](https://github.com/StackExchange/StackExchange.Redis/pull/1921))
- Adds: `DefaultOptionsProvider` support for endpoint-based defaults configuration ([#1987 by NickCraver](https://github.com/StackExchange/StackExchange.Redis/pull/1987))
- Adds: Envoy proxy support ([#1989 by rkarthick](https://github.com/StackExchange/StackExchange.Redis/pull/1989))
- Performance: When `SUBSCRIBE` is disabled, give proper errors and connect faster ([#2001 by NickCraver](https://github.com/StackExchange/StackExchange.Redis/pull/2001))
Expand Down
1 change: 1 addition & 0 deletions src/StackExchange.Redis/Enums/RedisCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ internal enum RedisCommand
SLAVEOF,
SLOWLOG,
SMEMBERS,
SMISMEMBER,
SMOVE,
SORT,
SPOP,
Expand Down
16 changes: 15 additions & 1 deletion src/StackExchange.Redis/Interfaces/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,7 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// Returns if member is a member of the set stored at key.
/// </summary>
/// <param name="key">The key of the set.</param>
/// <param name="value">The value to check for .</param>
/// <param name="value">The value to check for.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>
/// <see langword="true"/> if the element is a member of the set.
Expand All @@ -1115,6 +1115,20 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <remarks>https://redis.io/commands/sismember</remarks>
bool SetContains(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns whether each member is a member of the set stored at key.
/// </summary>
/// <param name="key">The key of the set.</param>
/// <param name="values">The members to check for.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>
/// An array of booleans corresponding to <paramref name="values"/>, for each:
/// <see langword="true"/> if the element is a member of the set.
/// <see langword="false"/> if the element is not a member of the set, or if key does not exist.
/// </returns>
/// <remarks>https://redis.io/commands/smismember</remarks>
bool[] SetContains(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns the set cardinality (number of elements) of the set stored at key.
/// </summary>
Expand Down
13 changes: 13 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,19 @@ public interface IDatabaseAsync : IRedisAsync
/// <remarks>https://redis.io/commands/sismember</remarks>
Task<bool> SetContainsAsync(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns whether each member is a member of the set stored at key.
/// </summary>
/// <param name="key">The key of the set.</param>
/// <param name="values">The members to check for.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>
/// <see langword="true"/> if the element is a member of the set.
/// <see langword="false"/> if the element is not a member of the set, or if key does not exist.
/// </returns>
/// <remarks>https://redis.io/commands/smismember</remarks>
Task<bool[]> SetContainsAsync(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Returns the set cardinality (number of elements) of the set stored at key.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions src/StackExchange.Redis/KeyspaceIsolation/DatabaseWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ public RedisValue[] SetCombine(SetOperation operation, RedisKey first, RedisKey
public bool SetContains(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) =>
Inner.SetContains(ToInner(key), value, flags);

public bool[] SetContains(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) =>
Inner.SetContains(ToInner(key), values, flags);

public long SetLength(RedisKey key, CommandFlags flags = CommandFlags.None) =>
Inner.SetLength(ToInner(key), flags);

Expand Down
3 changes: 3 additions & 0 deletions src/StackExchange.Redis/KeyspaceIsolation/WrapperBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,9 @@ public Task<RedisValue[]> SetCombineAsync(SetOperation operation, RedisKey first
public Task<bool> SetContainsAsync(RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None) =>
Inner.SetContainsAsync(ToInner(key), value, flags);

public Task<bool[]> SetContainsAsync(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) =>
Inner.SetContainsAsync(ToInner(key), values, flags);

public Task<long> SetLengthAsync(RedisKey key, CommandFlags flags = CommandFlags.None) =>
Inner.SetLengthAsync(ToInner(key), flags);

Expand Down
2 changes: 2 additions & 0 deletions src/StackExchange.Redis/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ StackExchange.Redis.IDatabase.SetCombine(StackExchange.Redis.SetOperation operat
StackExchange.Redis.IDatabase.SetCombineAndStore(StackExchange.Redis.SetOperation operation, StackExchange.Redis.RedisKey destination, StackExchange.Redis.RedisKey first, StackExchange.Redis.RedisKey second, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long
StackExchange.Redis.IDatabase.SetCombineAndStore(StackExchange.Redis.SetOperation operation, StackExchange.Redis.RedisKey destination, StackExchange.Redis.RedisKey[]! keys, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long
StackExchange.Redis.IDatabase.SetContains(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue value, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> bool
StackExchange.Redis.IDatabase.SetContains(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! values, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> bool[]!
StackExchange.Redis.IDatabase.SetLength(StackExchange.Redis.RedisKey key, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long
StackExchange.Redis.IDatabase.SetMembers(StackExchange.Redis.RedisKey key, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisValue[]!
StackExchange.Redis.IDatabase.SetMove(StackExchange.Redis.RedisKey source, StackExchange.Redis.RedisKey destination, StackExchange.Redis.RedisValue value, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> bool
Expand Down Expand Up @@ -763,6 +764,7 @@ StackExchange.Redis.IDatabaseAsync.SetCombineAndStoreAsync(StackExchange.Redis.S
StackExchange.Redis.IDatabaseAsync.SetCombineAsync(StackExchange.Redis.SetOperation operation, StackExchange.Redis.RedisKey first, StackExchange.Redis.RedisKey second, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisValue[]!>!
StackExchange.Redis.IDatabaseAsync.SetCombineAsync(StackExchange.Redis.SetOperation operation, StackExchange.Redis.RedisKey[]! keys, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisValue[]!>!
StackExchange.Redis.IDatabaseAsync.SetContainsAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue value, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<bool>!
StackExchange.Redis.IDatabaseAsync.SetContainsAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! values, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<bool[]!>!
StackExchange.Redis.IDatabaseAsync.SetLengthAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<long>!
StackExchange.Redis.IDatabaseAsync.SetMembersAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisValue[]!>!
StackExchange.Redis.IDatabaseAsync.SetMoveAsync(StackExchange.Redis.RedisKey source, StackExchange.Redis.RedisKey destination, StackExchange.Redis.RedisValue value, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<bool>!
Expand Down
3 changes: 3 additions & 0 deletions src/StackExchange.Redis/RawResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ internal bool GetBoolean()
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal string?[]? GetItemsAsStrings() => this.ToArray<string?>((in RawResult x) => (string?)x.AsRedisValue());

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal bool[]? GetItemsAsBooleans() => this.ToArray<bool>((in RawResult x) => (bool)x.AsRedisValue());

internal GeoPosition? GetItemsAsGeoPosition()
{
var items = GetItems();
Expand Down
12 changes: 12 additions & 0 deletions src/StackExchange.Redis/RedisDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1383,6 +1383,18 @@ public Task<bool> SetContainsAsync(RedisKey key, RedisValue value, CommandFlags
return ExecuteAsync(msg, ResultProcessor.Boolean);
}

public bool[] SetContains(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.SMISMEMBER, key, values);
return ExecuteSync(msg, ResultProcessor.BooleanArray, defaultValue: Array.Empty<bool>());
}

public Task<bool[]> SetContainsAsync(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.SMISMEMBER, key, values);
return ExecuteAsync(msg, ResultProcessor.BooleanArray, defaultValue: Array.Empty<bool>());
}

public long SetLength(RedisKey key, CommandFlags flags = CommandFlags.None)
{
var msg = Message.Create(Database, flags, RedisCommand.SCARD, key);
Expand Down
19 changes: 19 additions & 0 deletions src/StackExchange.Redis/ResultProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ public static readonly ResultProcessor<RedisValue[]>
public static readonly ResultProcessor<string?[]>
StringArray = new StringArrayProcessor();

public static readonly ResultProcessor<bool[]>
BooleanArray = new BooleanArrayProcessor();

public static readonly ResultProcessor<GeoPosition?[]>
RedisGeoPositionArray = new RedisValueGeoPositionArrayProcessor();
public static readonly ResultProcessor<GeoPosition?>
Expand Down Expand Up @@ -1262,6 +1265,22 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes
}
}

private sealed class BooleanArrayProcessor : ResultProcessor<bool[]>
{
protected override bool SetResultCore(PhysicalConnection connection, Message message, in RawResult result)
{
switch (result.Type)
{
case ResultType.MultiBulk when !result.IsNull:
var arr = result.GetItemsAsBooleans()!;

SetResult(message, arr);
return true;
}
return false;
}
}

private sealed class RedisValueGeoPositionProcessor : ResultProcessor<GeoPosition?>
{
protected override bool SetResultCore(PhysicalConnection connection, Message message, in RawResult result)
Expand Down
8 changes: 8 additions & 0 deletions tests/StackExchange.Redis.Tests/DatabaseWrapperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,14 @@ public void SetContains()
mock.Verify(_ => _.SetContains("prefix:key", "value", CommandFlags.None));
}

[Fact]
public void SetContains_2()
{
RedisValue[] values = new RedisValue[] { "value1", "value2" };
wrapper.SetContains("key", values, CommandFlags.None);
mock.Verify(_ => _.SetContains("prefix:key", values, CommandFlags.None));
}

[Fact]
public void SetLength()
{
Expand Down
Loading