265 lines
9.2 KiB
C#
265 lines
9.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Collections.Concurrent;
|
|
|
|
|
|
using Newtonsoft.Json;
|
|
using Amazon.Runtime;
|
|
using Amazon.DynamoDBv2;
|
|
using Amazon.DynamoDBv2.DocumentModel;
|
|
using Amazon.DynamoDBv2.Model;
|
|
using Axion.Collections.Concurrent;
|
|
|
|
|
|
|
|
using DYNAMO_DB_TABLE_NAME = System.String;
|
|
using DYNAMO_DB_TABLE_FULL_NAME = System.String;
|
|
using MongoDB.Driver.Core.Configuration;
|
|
|
|
|
|
namespace ServerCore;
|
|
|
|
|
|
// HANDOVER: AmazonDynamoDBClient SDK Wrapper 클래스 이다.
|
|
// Table 생성시 없으면 자동 생성 기능을 제공 한다.
|
|
|
|
|
|
public abstract class DynamoDbConnectorBase
|
|
{
|
|
// 하나의 아이템 최대 저장 크기 : PK + SK + ITEM <= ITEM_MAX_SIZE_BYTES
|
|
public static readonly UInt32 ITEM_MAX_SIZE_BYTES = 400 * 1024;
|
|
|
|
private AmazonDynamoDBClient? m_db_client;
|
|
private ConcurrentDictionary<DYNAMO_DB_TABLE_NAME, DYNAMO_DB_TABLE_FULL_NAME> m_to_load_table_names = new();
|
|
|
|
private string m_access_key = string.Empty;
|
|
private string m_secret_key = string.Empty;
|
|
private AmazonDynamoDBConfig? m_db_config;
|
|
|
|
private ConcurrentDictionary<DYNAMO_DB_TABLE_FULL_NAME, Table> m_loaded_tables = new();
|
|
|
|
public bool connectToDb(string accessKey, string secretKey, AmazonDynamoDBConfig dbConfig)
|
|
{
|
|
m_access_key = accessKey;
|
|
m_secret_key = secretKey;
|
|
m_db_config = dbConfig;
|
|
|
|
try
|
|
{
|
|
m_db_client = new AmazonDynamoDBClient(accessKey, secretKey, dbConfig);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().error($"Exception !!!, Failed to perform in DynamoDbConnectorBase.connectToDb() !!! : exception:{e}, AccessKey:{accessKey}, SecretKey:{secretKey} - {toBasicString()}");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<bool> isExistTable(string tableName)
|
|
{
|
|
try
|
|
{
|
|
if (m_db_client == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var loaded_tables = await m_db_client.ListTablesAsync();
|
|
return loaded_tables.TableNames.Contains(tableName);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perform in DynamoDbConnectorBase.isExistTable() !!! : exception:{e}, toFindTableName{tableName}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static async Task<bool> createTable( AmazonDynamoDBClient dbClient, DYNAMO_DB_TABLE_FULL_NAME tableFullName
|
|
, UpdateTimeToLiveRequest ttlUpdate
|
|
, List<AttributeDefinition> tableAttributes
|
|
, List<KeySchemaElement> tableKeySchema )
|
|
{
|
|
var request = new CreateTableRequest
|
|
{
|
|
TableName = tableFullName,
|
|
AttributeDefinitions = tableAttributes,
|
|
KeySchema = tableKeySchema,
|
|
BillingMode = BillingMode.PAY_PER_REQUEST
|
|
};
|
|
|
|
try
|
|
{
|
|
var new_table = await dbClient.CreateTableAsync(request);
|
|
Log.getLogger().info($"Created DynamoDB Table : {new_table.TableDescription.TableName}");
|
|
|
|
var ttl_res = await dbClient.UpdateTimeToLiveAsync(ttlUpdate);
|
|
if (System.Net.HttpStatusCode.OK != ttl_res.HttpStatusCode)
|
|
{
|
|
Log.getLogger().fatal($"Failed to UpdateTimeToLiveAsync() !!!, not configured TTL : {ttlUpdate.TimeToLiveSpecification.AttributeName}, toCreateTableName{tableFullName}");
|
|
return false;
|
|
}
|
|
|
|
var ttl_status_res = await dbClient.DescribeTimeToLiveAsync(new DescribeTimeToLiveRequest { TableName = tableFullName });
|
|
if (TimeToLiveStatus.ENABLED != ttl_status_res.TimeToLiveDescription.TimeToLiveStatus)
|
|
{
|
|
Log.getLogger().fatal($"Failed to check configured TTL !!! : ttlName:{ttlUpdate.TimeToLiveSpecification.AttributeName}, toCreateTableName{tableFullName}");
|
|
return false;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perform in DynamoDbConnectorBase.createTable() !!! : exception:{e}, toCreateTableName{tableFullName}");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static bool checkItemSizeLimit(string itemString)
|
|
{
|
|
var bytes = Encoding.UTF8.GetBytes(itemString);
|
|
if (bytes.Length > ITEM_MAX_SIZE_BYTES)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<bool> createTable( DYNAMO_DB_TABLE_FULL_NAME tableFullName
|
|
, List<AttributeDefinition> tableAttributes
|
|
, List<KeySchemaElement> tableKeySchema
|
|
, List<GlobalSecondaryIndex> globalSecondaryIndexes)
|
|
{
|
|
|
|
|
|
var request = new CreateTableRequest
|
|
{
|
|
TableName = tableFullName,
|
|
AttributeDefinitions = tableAttributes,
|
|
KeySchema = tableKeySchema,
|
|
GlobalSecondaryIndexes = globalSecondaryIndexes,
|
|
BillingMode = BillingMode.PAY_PER_REQUEST
|
|
};
|
|
|
|
try
|
|
{
|
|
if (m_db_client == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var new_table = await m_db_client.CreateTableAsync(request);
|
|
|
|
Log.getLogger().info($"Created DynamoDB Table : {new_table.TableDescription.TableName}");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perform in DynamoDbConnectorBase.createTable() !!! : exception:{e}, toCreateTableName{tableFullName}");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<bool> deleteTables(List<DYNAMO_DB_TABLE_FULL_NAME> tableFullNames)
|
|
{
|
|
|
|
foreach(var table_full_name in tableFullNames)
|
|
{
|
|
var request = new DeleteTableRequest
|
|
{
|
|
TableName = table_full_name,
|
|
};
|
|
|
|
try
|
|
{
|
|
if (m_db_client == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var deleted_table = await m_db_client.DeleteTableAsync(request);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perform in DynamoDbConnectorBase.deleteTables() !!! : exception:{e}, toDeleteTableName{table_full_name}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<TableDescription?> getTableDescription(DYNAMO_DB_TABLE_FULL_NAME tableFullName)
|
|
{
|
|
try
|
|
{
|
|
if (m_db_client == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var response = await m_db_client.DescribeTableAsync(tableFullName);
|
|
return response.Table;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perform in DynamoDbConnectorBase.getTableDescription() !!! : exception:{e}, TableName{tableFullName}");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public Table getTableByName(DYNAMO_DB_TABLE_NAME tableName)
|
|
{
|
|
m_to_load_table_names.TryGetValue(tableName, out var table_full_name);
|
|
NullReferenceCheckHelper.throwIfNull(table_full_name, () => $"table_full_name is null !!! : tableName:{tableName}");
|
|
|
|
m_loaded_tables.TryGetValue(table_full_name, out var table);
|
|
NullReferenceCheckHelper.throwIfNull(table, () => $"table is null !!!, Not found DynamoDb Table !!! : tableFullName:{table_full_name}");
|
|
return table;
|
|
}
|
|
|
|
public Table getTableByFullName(DYNAMO_DB_TABLE_FULL_NAME tableFullName)
|
|
{
|
|
m_loaded_tables.TryGetValue(tableFullName, out var table);
|
|
NullReferenceCheckHelper.throwIfNull(table, () => $"table is null !!!, Not found DynamoDb Table !!! : tableFullName:{tableFullName}");
|
|
return table;
|
|
}
|
|
|
|
public bool addTable(DYNAMO_DB_TABLE_FULL_NAME tableFullName, Table loadedTable)
|
|
{
|
|
return m_loaded_tables.TryAdd(tableFullName, loadedTable);
|
|
}
|
|
|
|
public bool hasTableName(DYNAMO_DB_TABLE_NAME tableName) => m_to_load_table_names.ContainsKey(tableName);
|
|
|
|
public DYNAMO_DB_TABLE_FULL_NAME getTableFullName(DYNAMO_DB_TABLE_NAME tableName)
|
|
{
|
|
m_to_load_table_names.TryGetValue(tableName, out var table_full_name);
|
|
NullReferenceCheckHelper.throwIfNull(table_full_name, () => $"table_full_name is null !!! : tableName:{tableName}");
|
|
return table_full_name;
|
|
}
|
|
|
|
public ConcurrentDictionary<DYNAMO_DB_TABLE_NAME, DYNAMO_DB_TABLE_FULL_NAME> getTableNames() => m_to_load_table_names;
|
|
|
|
protected bool addTableFullName(DYNAMO_DB_TABLE_NAME tableName, DYNAMO_DB_TABLE_FULL_NAME tableFullName) => m_to_load_table_names.TryAdd(tableName, tableFullName);
|
|
|
|
public string toConnectionKeyString()
|
|
{
|
|
return $"AccessKey:{m_access_key}, SecretKey:{m_secret_key}";
|
|
}
|
|
|
|
public string toBasicString()
|
|
{
|
|
return $"ServerUrl:{m_db_config?.ServiceURL}, RegionEndPoint:{m_db_config?.RegionEndpoint}";
|
|
}
|
|
|
|
public AmazonDynamoDBClient? getDbClient() => m_db_client;
|
|
}
|