You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
- Each tool can have a number of deployments which are rolled out over time. Clients can specify a "phase" value indicating where in the queue they want to take updates (ie. whether they want to be early- or late-adopters), and deployments can be paused and cancelled. - Tool channels are configured through the global configuration file. Tools can be marked "public", meaning that they do not require authentication against Horde for access. This can be useful for auto-update scenarios. - The most recent 5 deployments are kept in the tool at any time. The collection and controller implementation here is an experiment in reducing the amount of boilerplate currently adopted as a pattern in Horde. Notably: - Model and collection classes are concrete rather than interfaces (since we don't generally mock them anyway). - The same model class with annotations is used for response objects (paving the way to supporting patching and filtering using the same public model as the internal model). - The VersionedCollection class is used to handle automatic migration of documents across schema versions, and cache document values with Redis. - MongoDB property names are explicit and short, rather than just taking variable names. #preflight none [CL 19636699 by Ben Marsh in ue5-main branch]
112 lines
4.0 KiB
C#
112 lines
4.0 KiB
C#
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
using StackExchange.Redis;
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace EpicGames.Redis
|
|
{
|
|
/// <summary>
|
|
/// Represents a typed Redis list with a given key
|
|
/// </summary>
|
|
/// <typeparam name="TElement">The type of element stored in the list</typeparam>
|
|
public readonly struct RedisString<TElement>
|
|
{
|
|
internal readonly IDatabaseAsync Database;
|
|
|
|
/// <summary>
|
|
/// The key for the list
|
|
/// </summary>
|
|
public readonly RedisKey Key { get; }
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
/// <param name="database"></param>
|
|
/// <param name="key"></param>
|
|
public RedisString(IDatabaseAsync database, RedisKey key)
|
|
{
|
|
Database = database;
|
|
Key = key;
|
|
}
|
|
|
|
/// <inheritdoc cref="IDatabaseAsync.StringLengthAsync(RedisKey, CommandFlags)"/>
|
|
public Task<long> LengthAsync(CommandFlags flags = CommandFlags.None)
|
|
{
|
|
return Database.StringLengthAsync(Key, flags);
|
|
}
|
|
|
|
/// <inheritdoc cref="IDatabaseAsync.StringSetAsync(RedisKey, RedisValue, TimeSpan?, When, CommandFlags)"/>
|
|
public Task<bool> SetAsync(TElement value, TimeSpan? expiry = null, When when = When.Always, CommandFlags flags = CommandFlags.None)
|
|
{
|
|
return Database.StringSetAsync(Key, RedisSerializer.Serialize(value), expiry, when, flags);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Extension methods for sets
|
|
/// </summary>
|
|
public static class RedisStringExtensions
|
|
{
|
|
/// <inheritdoc cref="IDatabaseAsync.KeyDeleteAsync(RedisKey, CommandFlags)"/>
|
|
public static Task<bool> DeleteAsync<TElement>(this RedisString<TElement> str, CommandFlags flags = CommandFlags.None)
|
|
{
|
|
return str.Database.KeyDeleteAsync(str.Key, flags);
|
|
}
|
|
|
|
/// <inheritdoc cref="IDatabaseAsync.StringGetAsync(RedisKey, CommandFlags)"/>
|
|
public static async Task<TElement?> GetAsync<TElement>(this RedisString<TElement> str, CommandFlags flags = CommandFlags.None) where TElement : class
|
|
{
|
|
RedisValue value = await str.Database.StringGetAsync(str.Key, flags);
|
|
if (value.IsNullOrEmpty)
|
|
{
|
|
return null;
|
|
}
|
|
return RedisSerializer.Deserialize<TElement>(value);
|
|
}
|
|
|
|
/// <inheritdoc cref="IDatabaseAsync.StringGetAsync(RedisKey, CommandFlags)"/>
|
|
public static async Task<TElement?> GetValueAsync<TElement>(this RedisString<TElement> str, CommandFlags flags = CommandFlags.None) where TElement : struct
|
|
{
|
|
RedisValue value = await str.Database.StringGetAsync(str.Key, flags);
|
|
if (value.IsNullOrEmpty)
|
|
{
|
|
return default(TElement);
|
|
}
|
|
return RedisSerializer.Deserialize<TElement>(value);
|
|
}
|
|
|
|
/// <inheritdoc cref="IDatabaseAsync.StringDecrementAsync(RedisKey, Int64, CommandFlags)"/>
|
|
public static Task<long> DecrementAsync(this RedisString<long> str, long value = 1L, CommandFlags flags = CommandFlags.None)
|
|
{
|
|
return str.Database.StringDecrementAsync(str.Key, value, flags);
|
|
}
|
|
|
|
/// <inheritdoc cref="IDatabaseAsync.StringDecrementAsync(RedisKey, Double, CommandFlags)"/>
|
|
public static Task<double> DecrementAsync(this RedisString<double> str, double value = 1.0, CommandFlags flags = CommandFlags.None)
|
|
{
|
|
return str.Database.StringDecrementAsync(str.Key, value, flags);
|
|
}
|
|
|
|
/// <inheritdoc cref="IDatabaseAsync.StringDecrementAsync(RedisKey, Double, CommandFlags)"/>
|
|
public static Task<long> IncrementAsync(this RedisString<long> str, long value = 1L, CommandFlags flags = CommandFlags.None)
|
|
{
|
|
return str.Database.StringIncrementAsync(str.Key, value, flags);
|
|
}
|
|
|
|
/// <inheritdoc cref="IDatabaseAsync.StringDecrementAsync(RedisKey, Double, CommandFlags)"/>
|
|
public static Task<double> IncrementAsync(this RedisString<double> str, double value = 1.0, CommandFlags flags = CommandFlags.None)
|
|
{
|
|
return str.Database.StringIncrementAsync(str.Key, value, flags);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a version of this string which modifies a transaction rather than the direct DB
|
|
/// </summary>
|
|
public static RedisString<TElement> With<TElement>(this ITransaction transaction, RedisString<TElement> str)
|
|
{
|
|
return new RedisString<TElement>(transaction, str.Key);
|
|
}
|
|
}
|
|
}
|