Files
caliverse_server/ServerBase/Redis/RedisRequestWithLambdaBase.cs
2025-05-01 07:20:41 +09:00

279 lines
12 KiB
C#

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<TConditionContext>
{
private readonly RedisConnector m_redis_connector;
private readonly List<RedisKeyFormat> m_template_formats = new();
public Func<TConditionContext, Task<Result>> checkCondition { get; }
public Func<REDIS_KEY[], object[], Task<IWithResult>> doAction { get; }
public RedisExecutionHandler( RedisConnector redisConnector
, Func<TConditionContext, Task<Result>> condition
, RedisKeyFormat[] redisKeyFormats
, Func<REDIS_KEY[], object[], Task<IWithResult>> action )
{
m_redis_connector = redisConnector;
checkCondition = condition;
m_template_formats.AddRange(redisKeyFormats);
doAction = action;
}
public REDIS_KEY[] replaceKey(Dictionary<REDIS_KEY_FORMAT_TYPE, Dictionary<REDIS_KEY_PLACE_HOLDER, REDIS_KEY_REPLACE>> 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<REDIS_KEY>();
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<TConditionContext>
{
private readonly RedisConnector m_redis_connector;
private readonly ConcurrentDictionary<REDIS_REQUEST_HANDLER_TYPE, RedisExecutionHandler<TConditionContext>> m_handlers = new();
public RedisRequestWithLambdaBase(RedisConnector redisConnector)
{
m_redis_connector = redisConnector;
}
public bool registerRequestHandler( REDIS_REQUEST_HANDLER_TYPE handlerType
, RedisKeyFormat[] redisKeyFormats
, Func<TConditionContext, Task<Result>> condition
, Func<REDIS_KEY[], object[], Task<IWithResult>> handler )
{
var redis_connector = getRedisConnector();
NullReferenceCheckHelper.throwIfNull(redis_connector, () => $"redis_connector is null !!! - {toBasicString()}");
if (false == m_handlers.TryAdd(handlerType, new RedisExecutionHandler<TConditionContext>( 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<REDIS_KEY[], object[], Task<IWithResult>> handler )
{
return registerRequestHandler( handlerType
, redisKeyFormats
, _ => Task.FromResult(new Result())
, handler );
}
public async Task<IWithResult> executeRequestHandlerByHandlerType( REDIS_REQUEST_HANDLER_TYPE handlerType
, TConditionContext conditionContext
, Dictionary<REDIS_KEY_FORMAT_TYPE, Dictionary<REDIS_KEY_PLACE_HOLDER, REDIS_KEY_REPLACE>> 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<IWithResult> executeRequestHandlerByHandlerType( REDIS_REQUEST_HANDLER_TYPE handlerType
, Dictionary<REDIS_KEY_FORMAT_TYPE, Dictionary<REDIS_KEY_PLACE_HOLDER, REDIS_KEY_REPLACE>> 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<IWithResult> 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<REDIS_REQUEST_HANDLER_TYPE, IWithResult>)> executeRequestHanlderAllByCondition( TConditionContext conditionContext
, Dictionary<REDIS_KEY_FORMAT_TYPE, Dictionary<REDIS_KEY_PLACE_HOLDER, REDIS_KEY_REPLACE>> formatTypeToReplaceParams
, params object[] handlerParams )
{
var is_success = false;
var err_msg = string.Empty;
var results = new Dictionary<REDIS_REQUEST_HANDLER_TYPE, IWithResult>();
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<REDIS_KEY_FORMAT_TYPE, Dictionary<REDIS_KEY_PLACE_HOLDER, REDIS_KEY_REPLACE>> 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<REDIS_KEY>();
}
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()}";
}
}