// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EpicGames.Core;
using StackExchange.Redis;
namespace EpicGames.Redis
{
///
/// Represents a typed Redis sorted set with a given key
///
/// The type of element stored in the set
public record struct RedisSortedSetKey(RedisKey Inner) : IRedisTypedKey
{
///
/// Implicit conversion to typed redis key.
///
/// Key to convert
public static implicit operator RedisSortedSetKey(string key) => new RedisSortedSetKey(new RedisKey(key));
}
///
/// Typed implementation of
///
/// The element type
public readonly struct SortedSetEntry : IEquatable>, IComparable, IComparable>
{
///
/// Accessor for the element type
///
public readonly T Element { get; }
///
/// The encoded element value
///
public readonly RedisValue ElementValue { get; }
///
/// Score for the entry
///
public readonly double Score { get; }
///
/// Constructor
///
///
public SortedSetEntry(SortedSetEntry entry)
{
Element = RedisSerializer.Deserialize(entry.Element)!;
ElementValue = entry.Element;
Score = entry.Score;
}
///
/// Constructor
///
///
///
public SortedSetEntry(T element, double score)
{
Element = element;
ElementValue = RedisSerializer.Serialize(element);
Score = score;
}
///
/// Deconstruct this item into a tuple
///
///
///
public void Deconstruct(out T outElement, out double outScore)
{
outElement = Element;
outScore = Score;
}
///
public override bool Equals(object? obj)
=> obj is SortedSetEntry ssObj && Equals(ssObj);
///
public override int GetHashCode()
=> HashCode.Combine(Score, Element);
///
public bool Equals(SortedSetEntry other)
=> Score == other.Score && Equals(Element, other.Element);
///
public int CompareTo(SortedSetEntry other)
=> Score.CompareTo(other.Score);
///
public int CompareTo(object? obj)
=> obj is SortedSetEntry ssObj ? CompareTo(ssObj) : -1;
///
public static bool operator ==(SortedSetEntry a, SortedSetEntry b)
=> a.Equals(b);
///
public static bool operator !=(SortedSetEntry a, SortedSetEntry b)
=> !a.Equals(b);
///
public static bool operator <=(SortedSetEntry a, SortedSetEntry b)
=> a.CompareTo(b) <= 0;
///
public static bool operator <(SortedSetEntry a, SortedSetEntry b)
=> a.CompareTo(b) < 0;
///
public static bool operator >=(SortedSetEntry a, SortedSetEntry b)
=> a.CompareTo(b) >= 0;
///
public static bool operator >(SortedSetEntry a, SortedSetEntry b)
=> a.CompareTo(b) > 0;
}
///
/// Extension methods for sets
///
public static class RedisSortedSetKeyExtensions
{
#region Conditions
///
public static Condition SortedSetContains(this RedisSortedSetKey key, TElement value)
=> Condition.SortedSetContains(key.Inner, RedisSerializer.Serialize(value));
///
public static Condition SortedSetEqual(this RedisSortedSetKey key, TElement value, RedisValue score)
=> Condition.SortedSetEqual(key.Inner, RedisSerializer.Serialize(value), score);
///
public static Condition SortedSetLengthEqual(this RedisSortedSetKey key, long length)
=> Condition.SortedSetLengthEqual(key.Inner, length);
///
public static Condition SortedSetLengthGreaterThan(this RedisSortedSetKey key, long length)
=> Condition.SortedSetLengthGreaterThan(key.Inner, length);
///
public static Condition SortedSetLengthLessThan(this RedisSortedSetKey key, long length)
=> Condition.SortedSetLengthLessThan(key.Inner, length);
///
public static Condition SortedSetNotContains(this RedisSortedSetKey key, TElement value)
=> Condition.SortedSetNotContains(key.Inner, RedisSerializer.Serialize(value));
///
public static Condition SortedSetNotEqual(this RedisSortedSetKey key, TElement value, RedisValue score)
=> Condition.SortedSetNotEqual(key.Inner, RedisSerializer.Serialize(value), score);
///
public static Condition SortedSetScoreExists(this RedisSortedSetKey key, RedisValue score)
=> Condition.SortedSetScoreExists(key.Inner, score);
///
public static Condition SortedSetScoreExists(this RedisSortedSetKey key, RedisValue score, RedisValue count)
=> Condition.SortedSetScoreExists(key.Inner, score, count);
#endregion
#region SortedSetAddAsync
///
public static Task SortedSetAddAsync(this IDatabaseAsync target, RedisSortedSetKey key, TElement value, double score, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetAddAsync(key.Inner, RedisSerializer.Serialize(value), score, when, flags);
}
///
public static Task SortedSetAddAsync(this IDatabaseAsync target, RedisSortedSetKey key, SortedSetEntry[] values, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetAddAsync(key.Inner, values.ConvertAll(x => new SortedSetEntry(x.ElementValue, x.Score)), when, flags);
}
#endregion
#region SortedSetLengthAsync
///
public static Task SortedSetLengthAsync(this IDatabaseAsync target, RedisSortedSetKey key, double min = Double.NegativeInfinity, double max = Double.PositiveInfinity, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetLengthAsync(key.Inner, min, max, exclude, flags);
}
#endregion
#region SortedSetLengthByValueAsync
///
public static Task SortedSetLengthByValueAsync(this IDatabaseAsync target, RedisSortedSetKey key, TElement min, TElement max, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetLengthByValueAsync(key.Inner, RedisSerializer.Serialize(min), RedisSerializer.Serialize(max), exclude, flags);
}
#endregion
#region SortedSetRandomMemberAsync
///
public static Task SortedSetRandomMemberAsync(this IDatabaseAsync target, RedisSortedSetKey key, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetRandomMemberAsync(key.Inner, flags).DeserializeAsync();
}
#endregion
#region SortedSetRandomMembersAsync
///
public static Task SortedSetRandomMembersAsync(this IDatabaseAsync target, RedisSortedSetKey key, long count, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetRandomMembersAsync(key.Inner, count, flags).DeserializeAsync();
}
#endregion
#region SortedSetRangeByRankAsync
///
public static Task SortedSetRangeByRankAsync(this IDatabaseAsync target, RedisSortedSetKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetRangeByRankAsync(key.Inner, start, stop, order, flags).DeserializeAsync();
}
#endregion
#region SortedSetRangeByRankWithScoresAsync
///
public static async Task[]> SortedSetRangeByRankWithScoresAsync(this IDatabaseAsync target, RedisSortedSetKey key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None)
{
SortedSetEntry[] values = await target.SortedSetRangeByRankWithScoresAsync(key.Inner, start, stop, order, flags);
return Array.ConvertAll(values, x => new SortedSetEntry(x));
}
#endregion
#region SortedSetRangeByScoreAsync
///
public static Task SortedSetRangeByScoreAsync(this IDatabaseAsync target, RedisSortedSetKey key, double start = Double.NegativeInfinity, double stop = Double.PositiveInfinity, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0L, long take = -1L, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetRangeByScoreAsync(key.Inner, start, stop, exclude, order, skip, take, flags).DeserializeAsync();
}
#endregion
#region SortedSetRangeByScoreWithScoresAsync
///
public static async Task[]> SortedSetRangeByScoreWithScoresAsync(this IDatabaseAsync target, RedisSortedSetKey key, double start = Double.NegativeInfinity, double stop = Double.PositiveInfinity, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0L, long take = -1L, CommandFlags flags = CommandFlags.None)
{
SortedSetEntry[] values = await target.SortedSetRangeByScoreWithScoresAsync(key.Inner, start, stop, exclude, order, skip, take, flags);
return Array.ConvertAll(values, x => new SortedSetEntry(x));
}
#endregion
#region SortedSetRangeByValueAsync
///
public static Task SortedSetRangeByValueAsync(this IDatabaseAsync target, RedisSortedSetKey key, TElement min, TElement max, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0L, long take = -1L, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetRangeByValueAsync(key.Inner, RedisSerializer.Serialize(min), RedisSerializer.Serialize(max), exclude, order, skip, take, flags).DeserializeAsync();
}
#endregion
#region SortedSetRankAsync
///
public static Task SortedSetRankAsync(this IDatabaseAsync target, RedisSortedSetKey key, TElement item, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetRankAsync(key.Inner, RedisSerializer.Serialize(item), order, flags);
}
#endregion
#region SortedSetRemoveAsync
///
public static Task SortedSetRemoveAsync(this IDatabaseAsync target, RedisSortedSetKey key, TElement value, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetRemoveAsync(key.Inner, RedisSerializer.Serialize(value), flags);
}
///
public static Task SortedSetRemoveAsync(this IDatabaseAsync target, RedisSortedSetKey key, TElement[] values, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetRemoveAsync(key.Inner, RedisSerializer.Serialize(values), flags);
}
#endregion
#region SortedSetRemoveRangeByRankAsync
///
public static Task SortedSetRemoveRangeByRankAsync(this IDatabaseAsync target, RedisSortedSetKey key, long start, long stop, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetRemoveRangeByRankAsync(key.Inner, start, stop, flags);
}
#endregion
#region SortedSetRemoveRangeByScoreAsync
///
public static Task SortedSetRemoveRangeByScoreAsync(this IDatabaseAsync target, RedisSortedSetKey key, double start, double stop, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetRemoveRangeByScoreAsync(key.Inner, start, stop, exclude, flags);
}
#endregion
#region SortedSetRemoveRangeByValueAsync
///
public static Task SortedSetRemoveRangeByValueAsync(this IDatabaseAsync target, RedisSortedSetKey key, TElement min, TElement max, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetRemoveRangeByValueAsync(key.Inner, RedisSerializer.Serialize(min), RedisSerializer.Serialize(max), exclude, flags);
}
#endregion
#region SortedSetScanAsync
///
public static async IAsyncEnumerable> SortedSetScanAsync(this IDatabaseAsync target, RedisSortedSetKey key, RedisValue pattern = default, int pageSize = 250, long cursor = 0, int pageOffset = 0, CommandFlags flags = CommandFlags.None)
{
await foreach (SortedSetEntry entry in target.SortedSetScanAsync(key.Inner, pattern, pageSize, cursor, pageOffset, flags))
{
yield return new SortedSetEntry(entry);
}
}
#endregion
#region SortedSetScoreAsync
///
public static Task SortedSetScoreAsync(this IDatabaseAsync target, RedisSortedSetKey key, TElement member, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetScoreAsync(key.Inner, RedisSerializer.Serialize(member), flags);
}
#endregion
#region SortedSetUpdateAsync
///
public static Task SortedSetUpdateAsync(this IDatabaseAsync target, RedisSortedSetKey key, TElement member, double score, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetUpdateAsync(key.Inner, RedisSerializer.Serialize(member), score, when, flags);
}
///
public static Task SortedSetUpdateAsync(this IDatabaseAsync target, RedisSortedSetKey key, SortedSetEntry[] values, SortedSetWhen when = SortedSetWhen.Always, CommandFlags flags = CommandFlags.None)
{
return target.SortedSetUpdateAsync(key.Inner, values.ConvertAll(x => new SortedSetEntry(RedisSerializer.Serialize(x.Element), x.Score)), when, flags);
}
#endregion
}
}