mirror of
https://github.com/barelyprofessional/KfChatDotNet.git
synced 2026-04-30 03:22:04 -04:00
Moved to Lazy<T> and a static class for handling Redis connections with some methods to make it easier to work with JSON. Completely untested.
This commit is contained in:
@@ -61,8 +61,7 @@ public class RouletteCommand : ICommand
|
|||||||
var settings = await SettingsProvider.GetMultipleValuesAsync([
|
var settings = await SettingsProvider.GetMultipleValuesAsync([
|
||||||
BuiltIn.Keys.KasinoGameDisabledMessageCleanupDelay,
|
BuiltIn.Keys.KasinoGameDisabledMessageCleanupDelay,
|
||||||
BuiltIn.Keys.KasinoRouletteEnabled,
|
BuiltIn.Keys.KasinoRouletteEnabled,
|
||||||
BuiltIn.Keys.KasinoRouletteCountdownDuration,
|
BuiltIn.Keys.KasinoRouletteCountdownDuration
|
||||||
BuiltIn.Keys.BotRedisConnectionString
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Check if roulette is enabled
|
// Check if roulette is enabled
|
||||||
@@ -84,8 +83,7 @@ public class RouletteCommand : ICommand
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var redis = await ConnectionMultiplexer.ConnectAsync(settings[BuiltIn.Keys.BotRedisConnectionString].Value!);
|
_redisDb = Redis.Multiplexer.GetDatabase();
|
||||||
_redisDb = redis.GetDatabase();
|
|
||||||
|
|
||||||
var countdownDuration = TimeSpan.FromSeconds(
|
var countdownDuration = TimeSpan.FromSeconds(
|
||||||
settings[BuiltIn.Keys.KasinoRouletteCountdownDuration].ToType<int>());
|
settings[BuiltIn.Keys.KasinoRouletteCountdownDuration].ToType<int>());
|
||||||
|
|||||||
@@ -37,15 +37,14 @@ public class ConversationContextManager
|
|||||||
|
|
||||||
public ConversationContextManager()
|
public ConversationContextManager()
|
||||||
{
|
{
|
||||||
var connectionString = SettingsProvider.GetValueAsync(BuiltIn.Keys.BotRedisConnectionString).Result;
|
if (!Redis.IsAvailable)
|
||||||
if (string.IsNullOrEmpty(connectionString.Value))
|
|
||||||
{
|
{
|
||||||
Logger.Error($"Can't initialize the Nora ConversationContextManager service as Redis isn't configured in {BuiltIn.Keys.BotRedisConnectionString}");
|
Logger.Error($"Can't initialize the Nora ConversationContextManager service as Redis isn't configured in {BuiltIn.Keys.BotRedisConnectionString} " +
|
||||||
|
$"or the Redis client failed to connect");
|
||||||
throw new InvalidOperationException("Redis isn't configured");
|
throw new InvalidOperationException("Redis isn't configured");
|
||||||
}
|
}
|
||||||
|
|
||||||
var redis = ConnectionMultiplexer.Connect(connectionString.Value);
|
_redisDb = Redis.Multiplexer.GetDatabase();
|
||||||
_redisDb = redis.GetDatabase();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetContextKeyAsync(string mode, int userId, int roomId)
|
public static string GetContextKeyAsync(string mode, int userId, int roomId)
|
||||||
|
|||||||
@@ -23,15 +23,14 @@ public class KasinoKrash : IDisposable
|
|||||||
{
|
{
|
||||||
_kfChatBot = kfChatBot;
|
_kfChatBot = kfChatBot;
|
||||||
_ct = ct;
|
_ct = ct;
|
||||||
var connectionString = SettingsProvider.GetValueAsync(BuiltIn.Keys.BotRedisConnectionString).Result;
|
if (!Redis.IsAvailable)
|
||||||
if (string.IsNullOrEmpty(connectionString.Value))
|
|
||||||
{
|
{
|
||||||
_logger.Error($"Can't initialize the Kasino Krash service as Redis isn't configured in {BuiltIn.Keys.BotRedisConnectionString}");
|
_logger.Error($"Can't initialize the Kasino Krash service as Redis isn't configured in {BuiltIn.Keys.BotRedisConnectionString} " +
|
||||||
|
$"or the Redis service failed to connect");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var redis = ConnectionMultiplexer.Connect(connectionString.Value);
|
_redisDb = Redis.Multiplexer.GetDatabase();
|
||||||
_redisDb = redis.GetDatabase();
|
|
||||||
//attempt to pull a game from the db in case the bot crashed while a game was ongoing. if so it will restart the run
|
//attempt to pull a game from the db in case the bot crashed while a game was ongoing. if so it will restart the run
|
||||||
TheGame = GetKrashState().Result;
|
TheGame = GetKrashState().Result;
|
||||||
if (TheGame != null) _ = RunGame();
|
if (TheGame != null) _ = RunGame();
|
||||||
|
|||||||
@@ -241,15 +241,14 @@ public class KasinoMines
|
|||||||
public KasinoMines(ChatBot kfChatBot, int gamblerId)
|
public KasinoMines(ChatBot kfChatBot, int gamblerId)
|
||||||
{
|
{
|
||||||
_kfChatBot = kfChatBot;
|
_kfChatBot = kfChatBot;
|
||||||
var connectionString = SettingsProvider.GetValueAsync(BuiltIn.Keys.BotRedisConnectionString).Result;
|
if (!Redis.IsAvailable)
|
||||||
if (string.IsNullOrEmpty(connectionString.Value))
|
|
||||||
{
|
{
|
||||||
_logger.Error($"Can't initialize the Kasino Mines service as Redis isn't configured in {BuiltIn.Keys.BotRedisConnectionString}");
|
_logger.Error($"Can't initialize the Kasino Mines service as Redis isn't configured in {BuiltIn.Keys.BotRedisConnectionString} " +
|
||||||
|
$"or the Redis service failed to connect");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var redis = ConnectionMultiplexer.Connect(connectionString.Value);
|
_redisDb = Redis.Multiplexer.GetDatabase();
|
||||||
_redisDb = redis.GetDatabase();
|
|
||||||
GetSavedGames(gamblerId).Wait();
|
GetSavedGames(gamblerId).Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,15 +22,14 @@ public class KasinoRain : IDisposable
|
|||||||
{
|
{
|
||||||
_kfChatBot = kfChatBot;
|
_kfChatBot = kfChatBot;
|
||||||
_ct = ct;
|
_ct = ct;
|
||||||
var connectionString = SettingsProvider.GetValueAsync(BuiltIn.Keys.BotRedisConnectionString).Result;
|
if (!Redis.IsAvailable)
|
||||||
if (string.IsNullOrEmpty(connectionString.Value))
|
|
||||||
{
|
{
|
||||||
_logger.Error($"Can't initialize the Kasino Rain service as Redis isn't configured in {BuiltIn.Keys.BotRedisConnectionString}");
|
_logger.Error($"Can't initialize the Kasino Rain service as Redis isn't configured in {BuiltIn.Keys.BotRedisConnectionString} " +
|
||||||
|
$"or the Redis service failed to connect");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var redis = ConnectionMultiplexer.Connect(connectionString.Value);
|
_redisDb = Redis.Multiplexer.GetDatabase();
|
||||||
_redisDb = redis.GetDatabase();
|
|
||||||
_rainTimerTask = Task.Run(RainTimerTask, ct);
|
_rainTimerTask = Task.Run(RainTimerTask, ct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
110
KfChatDotNetBot/Services/Redis.cs
Normal file
110
KfChatDotNetBot/Services/Redis.cs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
using KfChatDotNetBot.Settings;
|
||||||
|
using System.Text.Json;
|
||||||
|
using NLog;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
|
||||||
|
namespace KfChatDotNetBot.Services;
|
||||||
|
|
||||||
|
public static class Redis
|
||||||
|
{
|
||||||
|
public static bool IsAvailable => LazyMultiplexer.IsValueCreated;
|
||||||
|
// Claude told me this will act like a singleton ConnectionMultiplexer
|
||||||
|
// while keeping things nice and convenient with static methods
|
||||||
|
// FYI the exception will be thrown once, cached for the lifetime of the application
|
||||||
|
// If you configure a Redis connection string, you MUST restart the application
|
||||||
|
// https://learn.microsoft.com/en-us/dotnet/api/system.lazy-1?view=net-10.0#:~:text=Exception%20caching,-When
|
||||||
|
private static readonly Lazy<ConnectionMultiplexer> LazyMultiplexer =
|
||||||
|
new(() =>
|
||||||
|
{
|
||||||
|
var logger = LogManager.GetCurrentClassLogger();
|
||||||
|
var connectionString = SettingsProvider.GetValueAsync(BuiltIn.Keys.BotRedisConnectionString).Result.Value;
|
||||||
|
if (string.IsNullOrEmpty(connectionString))
|
||||||
|
{
|
||||||
|
logger.Error($"Could not initiate the lazy connection multiplexer for the Redis service as the " +
|
||||||
|
$"connection string is not configured in {BuiltIn.Keys.BotRedisConnectionString}. " +
|
||||||
|
$"Redis won't be available to anything that relies on it. " +
|
||||||
|
$"If you do configure {BuiltIn.Keys.BotRedisConnectionString}, YOU MUST RESTART THE BOT");
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ConnectionMultiplexer.Connect(
|
||||||
|
SettingsProvider.GetValueAsync(BuiltIn.Keys.BotRedisConnectionString).Result.Value ??
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"{BuiltIn.Keys.BotRedisConnectionString} not defined, cannot connect to Redis"));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.Error($"Caught an exception when connecting to Redis at {connectionString}");
|
||||||
|
logger.Error(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// You can just grab this from wherever if you want a ready to go Redis connection
|
||||||
|
// ReSharper disable once MemberCanBePrivate.Global
|
||||||
|
public static ConnectionMultiplexer Multiplexer => LazyMultiplexer.Value;
|
||||||
|
|
||||||
|
private static IDatabase Db => Multiplexer.GetDatabase();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches a key from Redis asynchronously and deserializes its JSON value to T.
|
||||||
|
/// Returns default(T) if the key doesn't exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Redis key</param>
|
||||||
|
public static async Task<T?> GetJsonAsync<T>(string key)
|
||||||
|
{
|
||||||
|
var value = await Db.StringGetAsync(key);
|
||||||
|
if (value.IsNullOrEmpty)
|
||||||
|
return default;
|
||||||
|
|
||||||
|
return JsonSerializer.Deserialize<T>(value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches a key from Redis synchronously and deserializes its JSON value to T.
|
||||||
|
/// Returns default(T) if the key doesn't exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Redis key</param>
|
||||||
|
public static T? GetJson<T>(string key)
|
||||||
|
{
|
||||||
|
var value = Db.StringGet(key);
|
||||||
|
if (value.IsNullOrEmpty)
|
||||||
|
return default;
|
||||||
|
|
||||||
|
return JsonSerializer.Deserialize<T>(value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously set a key to a given object serialized using JSON
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Redis key</param>
|
||||||
|
/// <param name="value">Object that you wish to serialize</param>
|
||||||
|
/// <param name="expires">Expiration (null means never expires)</param>
|
||||||
|
/// <param name="when">Redis behavior whether the key has a value or not
|
||||||
|
/// When.Always = set the value regardless of whether the key has a value
|
||||||
|
/// When.Exists = only set the value if the key has a value already
|
||||||
|
/// When.NotExists = only set the value if the key has no value
|
||||||
|
/// </param>
|
||||||
|
public static async Task SetJsonAsync(string key, object value, TimeSpan? expires = null, When when = When.Always)
|
||||||
|
{
|
||||||
|
await Db.StringSetAsync(key, JsonSerializer.Serialize(value), expires, when);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Synchronously set a key to a given object serialized using JSON
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Redis key</param>
|
||||||
|
/// <param name="value">Object that you wish to serialize</param>
|
||||||
|
/// <param name="expires">Expiration (null means never expires)</param>
|
||||||
|
/// <param name="when">Redis behavior whether the key has a value or not
|
||||||
|
/// When.Always = set the value regardless of whether the key has a value
|
||||||
|
/// When.Exists = only set the value if the key has a value already
|
||||||
|
/// When.NotExists = only set the value if the key has no value
|
||||||
|
/// </param>
|
||||||
|
public static void SetJson(string key, object value, TimeSpan? expires = null, When when = When.Always)
|
||||||
|
{
|
||||||
|
Db.StringSet(key, JsonSerializer.Serialize(value), expires, when);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user