Files
caliverse_server/ServerBase/DB/DynamoDb/DynamoDbClient.cs
2025-05-01 07:20:41 +09:00

276 lines
9.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;
using ServerCore;
using ServerBase;
using DYNAMO_DB_TABLE_NAME = System.String;
using DYNAMO_DB_TABLE_FULL_NAME = System.String;
namespace ServerBase;
public partial class DynamoDbClient : DynamoDbConnectorBase, IModule, IInitializer
{
public const string TTL_NAME = "TTL";
public const string SK_EMPTY = "empty";
public const string PK_GLOBAL = "global";
private readonly ModuleContext? m_module_context;
public DynamoDbClient()
: base()
{ }
public DynamoDbClient(ModuleContext moduleContext)
: base()
{
m_module_context = moduleContext;
}
public async Task<Result> onInit()
{
var err_msg = string.Empty;
var result = new Result();
var module_context = getModuleContext();
var config_param = module_context.getConfigParam() as ConfigParam;
NullReferenceCheckHelper.throwIfNull(config_param, () => $"config_param is null !!!");
result = connectToDb(config_param);
if (result.isFail())
{
err_msg = $"Failed to create DB Table !!! - {toBasicString()}";
Log.getLogger().fatal(result.toBasicString());
return result;
}
if (false == await createDBIfNotExists(false))
{
err_msg = $"Failed to createDBIfNotExists() !!! - {toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbTableCreateFailed, err_msg);
Log.getLogger().fatal(result.toBasicString());
return result;
}
return result;
}
public async Task<Result> startModule()
{
var result = new Result();
return await Task.FromResult(result);
}
public async Task<Result> stopModule()
{
var result = new Result();
return await Task.FromResult(result);
}
public Result connectToDb(ConfigParam configParam)
{
var result = new Result();
var err_msg = string.Empty;
(var error_code, var to_load_table_names) = ServerConfigHelper.getDynamoDbTableNamesWithServiceType(configParam.ServiceType);
if (error_code.isFail())
{
err_msg = $"Failed to DynamoDbClient.getDynamoDbTableNameWithServiceType() !!! : {configParam.toBasicString()} - {toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
return result;
}
return connectToDb( to_load_table_names
, configParam.IsLocalDynamoDB, configParam.UrlOfDynamoDb
, configParam.AccessKeyOfAws, configParam.SecretKeyOfAws, configParam.RegionOfAws );
}
public Result connectToDb( ConcurrentDictionary<DYNAMO_DB_TABLE_NAME, DYNAMO_DB_TABLE_FULL_NAME> tableNames, bool localDynamoDb
, string dynamodbUrl
, string awsAccessKey, string awsSecretKey
, string awsRegion = "" )
{
var result = new Result();
var err_msg = string.Empty;
foreach( var each in tableNames )
{
var table_name = each.Key;
var table_full_name = each.Value;
if(false == addTableFullName(table_name, table_full_name))
{
err_msg = $"Failed to addTableFullName() !!! : tableName:{table_name}, tableFullName:{table_full_name} - {toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbTableNameDuplicated, err_msg);
Log.getLogger().fatal(result.toBasicString());
return result;
}
}
var db_config = new AmazonDynamoDBConfig();
db_config.BufferSize = 4 * 1024 * 1024; // 4 MB
db_config.RetryMode = RequestRetryMode.Standard;
db_config.DisableLogging = false; // Logging is disabled by default. - Set to true to enable request-level logging.
db_config.ThrottleRetries = false; // Throttled requests are not automatically retried. - Set to false to automatically retry throttled requests.
if (localDynamoDb)
{
// DynamoDB-Local is running, so create a client
Log.getLogger().info($"Setting up a DynamoDB-Local client (DynamoDB Local seems to be running)");
db_config.ServiceURL = dynamodbUrl;
if (false == base.connectToDb(awsAccessKey, awsSecretKey, db_config))
{
err_msg = $"Failed to connect a DynamoDB-Local client !!! : {toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbConnectFailed, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
}
else
{
Log.getLogger().info($"Setting up a DynamoDB-Remote client : TargetRegion:{awsRegion}");
try
{
db_config.RegionEndpoint = Amazon.RegionEndpoint.GetBySystemName(awsRegion);
if (false == base.connectToDb(awsAccessKey, awsSecretKey, db_config))
{
err_msg = $"Failed to connect a DynamoDB-Remote client !!! : {toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbConnectFailed, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
}
catch (Exception e)
{
err_msg = $"Failed to connect a DynamoDB-Remote client !!! : Exception:{e}, {toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbConnectFailed, err_msg);
Log.getLogger().fatal(result.toBasicString());
return result;
}
}
return result;
}
public Result connectToDb( string tableName, bool localDynamoDB, string dynamodbUrl
, string awsAccessKey, string awsSecretKey, string awsRegion = "")
{
var table_names = new ConcurrentDictionary<DYNAMO_DB_TABLE_NAME, DYNAMO_DB_TABLE_FULL_NAME>();
table_names[tableName] = tableName;
return connectToDb( table_names, localDynamoDB, dynamodbUrl
, awsAccessKey, awsSecretKey, awsRegion );
}
public async Task<bool> createDBIfNotExists(bool resetTable)
{
var err_msg = string.Empty;
var db_client = getDbClient();
if (db_client == null)
{
err_msg = $"Not created DynamoDbClient !!! - {toBasicString()}";
Log.getLogger().fatal(err_msg);
return false;
}
var loaded_table_full_names = getTableNames().Values.ToList();
if (resetTable == true)
{
if(false == await deleteTables(loaded_table_full_names))
{
err_msg = $"Failed to DynamoDbClient.deleteTables() !!! - {toBasicString()}";
Log.getLogger().fatal(err_msg);
return false;
}
}
List<AttributeDefinition> tableAttributes = new List<AttributeDefinition>();
tableAttributes.Add(new AttributeDefinition(PrimaryKey.PK_Define, ScalarAttributeType.S));
tableAttributes.Add(new AttributeDefinition(PrimaryKey.SK_Define, ScalarAttributeType.S));
List<KeySchemaElement> tableKeySchema = new List<KeySchemaElement>();
tableKeySchema.Add(new KeySchemaElement(PrimaryKey.PK_Define, KeyType.HASH));
tableKeySchema.Add(new KeySchemaElement(PrimaryKey.SK_Define, KeyType.RANGE));
foreach (var table_full_name in loaded_table_full_names)
{
if (await isExistTable(table_full_name) == false)
{
var ttl_update = new UpdateTimeToLiveRequest
{
TableName = table_full_name,
TimeToLiveSpecification = new TimeToLiveSpecification
{
AttributeName = TTL_NAME, // TTL로 사용할 속성 이름
Enabled = true // TTL 사용 여부
}
};
if(false == await createTable( db_client, table_full_name, ttl_update
, tableAttributes, tableKeySchema ))
{
err_msg = $"Failed to DynamoDbClient.addTable() !!! - {toBasicString()}";
Log.getLogger().fatal(err_msg);
return false;
}
}
if(false == addTable(table_full_name, Table.LoadTable(db_client, table_full_name)))
{
err_msg = $"Failed to DynamoDbClient.addTable() !!! : tableName:{table_full_name} - {toBasicString()}";
Log.getLogger().fatal(err_msg);
return false;
}
}
DynamoDbQueryOperationOptionConfig.configure();
return true;
}
public Table getTableByDoc<TDoc>()
where TDoc : DynamoDbDocBase, new()
{
return getTableByName((new TDoc()).TableName);
}
public Table getTableByDoc<TDoc>(TDoc doc)
where TDoc : DynamoDbDocBase
{
return getTableByName(doc.TableName);
}
public ModuleContext getModuleContext()
{
NullReferenceCheckHelper.throwIfNull(m_module_context, () => $"m_module_context is null !!!");
return m_module_context;
}
}