using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections.Concurrent; using StackExchange.Redis; using ServerCore; using ServerBase; using REDIS_REQUEST_HANDLER_TYPE = System.UInt32; using REDIS_KEY_FORMAT_TYPE = System.UInt32; using REDIS_KEY_FORMAT = System.String; using REDIS_KEY_PLACE_HOLDER = System.String; using REDIS_KEY_REPLACE = System.String; using REDIS_KEY = System.String; namespace ServerBase; public class RedisKeyFormat { public REDIS_KEY_FORMAT_TYPE KeyType { get; set; } public string Format { get; set; } = string.Empty; public RedisKeyFormat(REDIS_KEY_FORMAT_TYPE keyType, REDIS_KEY_FORMAT format) { KeyType = keyType; Format = format; } } public class RedisExecutionHandler { private readonly RedisConnector m_redis_connector; private readonly List m_template_formats = new(); public Func> checkCondition { get; } public Func> doAction { get; } public RedisExecutionHandler( RedisConnector redisConnector , Func> condition , RedisKeyFormat[] redisKeyFormats , Func> action ) { m_redis_connector = redisConnector; checkCondition = condition; m_template_formats.AddRange(redisKeyFormats); doAction = action; } public REDIS_KEY[] replaceKey(Dictionary> formatTypeToReplaceParams) { ConditionValidCheckHelper.throwIfFalseWithCondition( () => m_template_formats.Count >= formatTypeToReplaceParams.Count , () => $"Invalid Count of KeyFormats and ReplaceParam !!! : keyFormatsCount:{m_template_formats.Count} >= replaceParamCount:{formatTypeToReplaceParams.Count}"); var redis_keys = new List(); foreach(var each in formatTypeToReplaceParams) { var format_type = each.Key; var place_holder_to_replace = each.Value; m_template_formats.ForEach((templateformat) => { if(format_type == templateformat.KeyType) { var resolved_key = TemplateReplacer.replace(templateformat.Format, place_holder_to_replace); redis_keys.Add(resolved_key); } }); } return redis_keys.ToArray(); } } public abstract class RedisRequestWithLambdaBase { private readonly RedisConnector m_redis_connector; private readonly ConcurrentDictionary> m_handlers = new(); public RedisRequestWithLambdaBase(RedisConnector redisConnector) { m_redis_connector = redisConnector; } public bool registerRequestHandler( REDIS_REQUEST_HANDLER_TYPE handlerType , RedisKeyFormat[] redisKeyFormats , Func> condition , Func> handler ) { var redis_connector = getRedisConnector(); NullReferenceCheckHelper.throwIfNull(redis_connector, () => $"redis_connector is null !!! - {toBasicString()}"); if (false == m_handlers.TryAdd(handlerType, new RedisExecutionHandler( getRedisConnector() , condition , redisKeyFormats, handler ) ) ) { Log.getLogger().error($"Failed to TryAdd() !!!, in registerRequestHandler(), Already registered : handlerType:{handlerType} - {toBasicString()}"); return false; } return true; } public bool registerRequestHandler( REDIS_REQUEST_HANDLER_TYPE handlerType , RedisKeyFormat[] redisKeyFormats , Func> handler ) { return registerRequestHandler( handlerType , redisKeyFormats , _ => Task.FromResult(new Result()) , handler ); } public async Task executeRequestHandlerByHandlerType( REDIS_REQUEST_HANDLER_TYPE handlerType , TConditionContext conditionContext , Dictionary> formatTypeToReplaceParams , params object[] handlerParams ) { var result = new Result(); var err_msg = string.Empty; if(false == m_handlers.TryGetValue(handlerType, out var found_handler)) { err_msg = $"Failed to TryGetValue() !!!, in executeHandlerByHandlerType(), Not found RedisExecutionHandler : handlerType:{handlerType} - {toBasicString()}"; result.setFail(ServerErrorCode.RedisRequestHandlerNotFound, err_msg); Log.getLogger().error(result.toBasicString()); return new ResultOnly(result); } NullReferenceCheckHelper.throwIfNull(found_handler, () => $"found_handler is null !!! - {toBasicString()}"); result = await found_handler.checkCondition(conditionContext); if(result.isFail()) { err_msg = $"Failed to checkCondition() !!!, in executeHandlerByHandlerType() : : handlerType:{handlerType}, {result.toBasicString()} - {toBasicString()}"; Log.getLogger().error(result.toBasicString()); return new ResultOnly(result); } var redis_keys = found_handler.replaceKey(formatTypeToReplaceParams); var with_result = await found_handler.doAction(redis_keys, handlerParams); if(with_result.Result.isFail()) { err_msg = $"Failed to doAction() !!!, in executeHandlerByHandlerType() : handlerType:{handlerType}, {with_result.Result.toBasicString()} - {toBasicString()}"; Log.getLogger().error(err_msg); return with_result; } return with_result; } public async Task executeRequestHandlerByHandlerType( REDIS_REQUEST_HANDLER_TYPE handlerType , Dictionary> formatTypeToReplaceParams , params object[] handlerParams) { var result = new Result(); var err_msg = string.Empty; if(false == m_handlers.TryGetValue(handlerType, out var found_handler)) { err_msg = $"Failed to TryGetValue() !!!, in executeHandlerByHandlerType(), Not found RedisExecutionHandler : handlerType:{handlerType} - {toBasicString()}"; result.setFail(ServerErrorCode.RedisRequestHandlerNotFound, err_msg); Log.getLogger().error(result.toBasicString()); return new ResultOnly(result); } NullReferenceCheckHelper.throwIfNull(found_handler, () => $"found_handler is null !!! - {toBasicString()}"); var redis_keys = found_handler.replaceKey(formatTypeToReplaceParams); var with_result = await found_handler.doAction(redis_keys, handlerParams); if(with_result.Result.isFail()) { err_msg = $"Failed to doAction() !!!, in executeHandlerByHandlerType() : handlerType:{handlerType}, {result.toBasicString()} - {toBasicString()}"; Log.getLogger().error(err_msg); return with_result; } return with_result; } public async Task executeRequestHandlerByHandlerType( REDIS_REQUEST_HANDLER_TYPE handlerType , REDIS_KEY[] redisKeys , params object[] handlerParams) { var result = new Result(); var err_msg = string.Empty; if(false == m_handlers.TryGetValue(handlerType, out var found_handler)) { err_msg = $"Failed to TryGetValue() !!!, in executeHandlerByHandlerType(), Not found RedisExecutionHandler : handlerType:{handlerType} - {toBasicString()}"; result.setFail(ServerErrorCode.RedisRequestHandlerNotFound, err_msg); Log.getLogger().error(result.toBasicString()); return new ResultOnly(result); } NullReferenceCheckHelper.throwIfNull(found_handler, () => $"found_handler is null !!! - {toBasicString()}"); var with_result = await found_handler.doAction(redisKeys, handlerParams); if(with_result.Result.isFail()) { err_msg = $"Failed to doAction() !!!, in executeHandlerByHandlerType() : handlerType:{handlerType}, {with_result.Result.toBasicString()} - {toBasicString()}"; Log.getLogger().error(err_msg); return with_result; } return with_result; } public async Task<(bool, Dictionary)> executeRequestHanlderAllByCondition( TConditionContext conditionContext , Dictionary> formatTypeToReplaceParams , params object[] handlerParams ) { var is_success = false; var err_msg = string.Empty; var results = new Dictionary(); foreach (var each in m_handlers) { var handler_type = each.Key; var handler = each.Value; var result_check = await handler.checkCondition(conditionContext); if (result_check.isFail()) { err_msg = $"Failed to checkCondition() !!!, in executeFunctionAllByCondition() : : handlerType:{handler_type}, {result_check.toBasicString()} - {toBasicString()}"; Log.getLogger().debug(err_msg); continue; } var redis_keys = handler.replaceKey(formatTypeToReplaceParams); var with_result = await handler.doAction(redis_keys, handlerParams); if (with_result.Result.isFail()) { err_msg = $"Failed to doAction() !!!, in executeFunctionAllByCondition() : handlerType:{handler_type}, {with_result.Result.toBasicString()} - {toBasicString()}"; Log.getLogger().error(err_msg); continue; } results.Add(handler_type, with_result); is_success = true; } return (is_success, results); } public REDIS_KEY[] replaceByHandlerType( REDIS_REQUEST_HANDLER_TYPE handlerType , Dictionary> formatTypeToReplaceParams) { var err_msg = string.Empty; if (false == m_handlers.TryGetValue(handlerType, out var found_handler)) { err_msg = $"Failed to TryGetValue() !!!, in resolveByHandlerType(), Not found RedisExecutionHandler : handlerType:{handlerType} - {toBasicString()}"; Log.getLogger().error(err_msg); return Array.Empty(); } NullReferenceCheckHelper.throwIfNull(found_handler, () => $"found_handler is null !!! - {toBasicString()}"); return found_handler.replaceKey(formatTypeToReplaceParams); } public RedisConnector getRedisConnector() => m_redis_connector; public string toBasicString() { return $"redisRequestor:{this.getTypeName()}"; } }