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

2505 lines
100 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.IO;
using System.Net;
using Google.Protobuf.WellKnownTypes;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.Runtime;
using StackExchange.Redis;
using NLog.LayoutRenderers;
using Renci.SshNet.Security;
using Amazon.S3.Model;
using Amazon.DynamoDBv2.DataModel;
using MongoDB.Bson;
using Microsoft.IdentityModel.Tokens;
using ServerCore; using ServerBase;
using DYNAMO_DB_TABLE_FULL_NAME = System.String;
using DYNAMO_DB_TABLE_NAME = System.String;
namespace ServerBase;
public static class DynamoDbClientHelper
{
public static QueryOperationConfig makeQueryConfigForReadByPKOnly(this DynamoDbClient dbClient, string pk)
{
QueryFilter filter = new QueryFilter();
filter.AddCondition(PrimaryKey.PK_Define, QueryOperator.Equal, pk);
QueryOperationConfig config = new QueryOperationConfig()
{
Filter = filter,
ConsistentRead = true
};
return config;
}
public static QueryOperationConfig makeQueryConfigWithPKOnly(this DynamoDbClient dbClient, string pk, QueryOperationConfig config)
{
QueryFilter filter = new QueryFilter();
filter.AddCondition(PrimaryKey.PK_Define, QueryOperator.Equal, pk);
config.Filter = filter;
return config;
}
public static QueryOperationConfig makeQueryConfigForReadByPKSK(this DynamoDbClient dbClient, string pk, string sk = DynamoDbClient.SK_EMPTY)
{
QueryFilter filter = new QueryFilter();
filter.AddCondition(PrimaryKey.PK_Define, QueryOperator.Equal, pk);
filter.AddCondition(PrimaryKey.SK_Define, QueryOperator.Equal, sk);
QueryOperationConfig config = new QueryOperationConfig()
{
Filter = filter,
ConsistentRead = true
};
return config;
}
public static QueryOperationConfig makeQueryConfigWithPKSKBySKBeginWith(this DynamoDbClient dbClient, string pk, string sk, QueryOperationConfig? config = null)
{
QueryFilter filter = new QueryFilter();
filter.AddCondition(PrimaryKey.PK_Define, QueryOperator.Equal, pk);
filter.AddCondition(PrimaryKey.SK_Define, QueryOperator.BeginsWith, (sk == string.Empty ? DynamoDbClient.SK_EMPTY : sk));
if(null == config)
{
config = new QueryOperationConfig();
}
config.Filter = filter;
return config;
}
public static bool isEmptySK(this string _this)
{
if (_this == null)
{
return false;
}
if (_this == DynamoDbClient.SK_EMPTY)
{
return true;
}
return false;
}
public static async Task<(Result, List<Document>)> simpleQueryWithQueryOperationConfig(this Table table, QueryOperationConfig queryOperationConfig, string eventTid = "")
{
var result = new Result();
var err_msg = string.Empty;
var documents = new List<Document>();
try
{
var search = table.queryWithStopwatch(queryOperationConfig, eventTid);
while (search.IsDone == false)
{
var next_documents = await search.GetNextSetAsync();
if (null == next_documents)
{
return (result, documents);
}
foreach (var document in next_documents)
{
documents.Add(document);
}
}
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbQueryException;
err_msg = $"Exception !!!, Failed to perform in simpleQueryWithQueryOperationConfig() !!! : errorCode:{error_code}, exception:{e} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
return (result, documents);
}
return (result, documents);
}
public static async Task<Result> simpleInsertDocument(this Table table, Document document, string eventTid = "")
{
var result = new Result();
var err_msg = string.Empty;
try
{
await table.putItemAsyncWithStopwatch(document, eventTid);
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleInsertDocument() !!! : errorCode:{error_code}, exception:{e}, {document.toBasicString()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
return result;
}
public static async Task<(Result, Document?)> simpleUpsertDocument(this Table table, Document document, string eventTid = "")
{
var result = new Result();
var err_msg = string.Empty;
Document? upserted_document;
try
{
upserted_document = await table.upsertItemAsyncWithStopwatch(document, eventTid);
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleUpsertDocument() : errorCode:{error_code}, exception:{e}, {document.toBasicString()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
return (result, upserted_document);
}
public static async Task<(Result, Document?)> simpleUpdateDocument(this Table table, Document document, string eventTid = "")
{
var result = new Result();
var err_msg = string.Empty;
Document? updated_document;
try
{
updated_document = await table.updateItemAsyncWithStopwatch(document, new UpdateItemOperationConfig
{
ConditionalExpression = new Expression
{
ExpressionStatement = $"attribute_exists({PrimaryKey.PK_Define}) AND attribute_exists({PrimaryKey.SK_Define})"
}
}, eventTid);
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleUpdateDocument() !!! : errorCode:{error_code}, exception:{e}, {document.toBasicString()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
return (result, updated_document);
}
public static async Task<Result> simpleDeleteDocument(this Table table, Document document, string eventTid = "")
{
var result = new Result();
var err_msg = string.Empty;
try
{
await table.deleteItemAsyncWithStopwatch(document, eventTid);
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Failed to perform in simpleDeleteDocument() !!! : : errorCode:{error_code}, exception:{e}, {document.toBasicString()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
return result;
}
public static async Task<Result> simpleUpsertDocumentsWithBatchWrite(this Table table, List<Document> toUpsertDocuments, string eventTid = "")
{
var result = new Result();
var err_msg = string.Empty;
try
{
if (toUpsertDocuments.Count > 0)
{
var batch = table.CreateBatchWrite();
foreach (var document in toUpsertDocuments)
{
batch.AddDocumentToPut(document);
}
await batch.executeAsyncWithStopwatch(eventTid);
}
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleUpsertDocumentsWithBatchWrite() !!! : errorCode:{error_code}, exception:{e}, {toUpsertDocuments.toBasicStringAll()} - tableName:{table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
return result;
}
public static async Task<Result> simpleDeleteDocumentsWithBatchWrite(this Table table, List<Document> toDeleteDocuments, string eventTid = "")
{
var result = new Result();
var err_msg = string.Empty;
try
{
if (toDeleteDocuments.Count > 0)
{
var batch = table.CreateBatchWrite();
foreach (var document in toDeleteDocuments)
{
batch.AddItemToDelete(document);
}
await batch.executeAsyncWithStopwatch(eventTid);
}
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleDeleteDocumentsWithBatchWrite() !!! : errorCode:{error_code}, exception:{e}, {toDeleteDocuments.toBasicStringAll()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
return result;
}
public static async Task<(Result, List<Document>)> simpleTransactReadWithDocument( this Table table
, List<(PrimaryKey, TransactGetItemOperationConfig?)> toReadTransactQueries
, UInt16 retryCount = 3
, string eventTid = "" )
{
var result = new Result();
var err_msg = string.Empty;
var read_documents = new List<Document>();
var transact_get = table.CreateTransactGet();
try
{
foreach (var read_query in toReadTransactQueries)
{
var primary_key = read_query.Item1;
var transact_config = read_query.Item2 != null ? read_query.Item2 : null;
transact_get.AddKey( primary_key.toPartitionKey()
, primary_key.toSortKey()
, transact_config );
}
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleTransactReadWithDocument() !!! : errorCode:{error_code}, exception:{e}, {toReadTransactQueries.toBasicStringAll()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, read_documents);
}
// 기본(1) + retryCount 만큼 처리 한다. - kangms
for (int i = 0; i <= retryCount; ++i)
{
if (i >= 1)
{
await Task.Delay(2000);
}
try
{
await transact_get.ExecuteAsync();
// 쿼리 순서와 동일하게 반환된 정보가 목록화 된다. !!! - kangms
for (var k = 0; k < transact_get.Results.Count; k++)
{
read_documents.Add(transact_get.Results[k]);
}
}
catch (TransactionConflictException e)
{
var error_code = ServerErrorCode.DynamoDbTransactionConflictException;
err_msg = $"TransactionConflictException !!!, Failed to perform in simpleTransactReadWithDocument() !!! : errorCode:{error_code}, exception:{e}, {toReadTransactQueries.toBasicStringAll()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
continue;
}
catch (TransactionCanceledException e)
{
var error_code = ServerErrorCode.DynamoDbTransactionCanceledException;
err_msg = $"TransactionCanceledException !!!, Failed to perform in simpleTransactReadWithDocument() !!! : errorCode:{error_code}, exception:{e}, {toReadTransactQueries.toBasicStringAll()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
continue;
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleTransactReadWithDocument() !!! : errorCode:{error_code}, exception:{e}, {toReadTransactQueries.toBasicStringAll()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
continue;
}
return (result, read_documents);
}
return (result, read_documents);
}
public static async Task<(Result, List<Document>)> simpleTransactWriteWithDocument( this Table table
, List<DynamoDbDocumentQueryContext> toWriteTransactQueries
, UInt16 retryCount = 3
, string eventTid = "" )
{
var result = new Result();
var err_msg = string.Empty;
var result_documents = new List<Document>();
var transact_write = table.CreateTransactWrite();
try
{
foreach (var write_query in toWriteTransactQueries)
{
if (false == write_query.isValid())
{
err_msg = $"DynamoDbDocumentQueryContext invalid !!! : {write_query.toBasicString()} - {table.toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbDocumentIsNullInQueryContext, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, result_documents);
}
var document = write_query.getDocument();
NullReferenceCheckHelper.throwIfNull(document, () => $"document is null !!! - {write_query.toBasicString()}, {table.toBasicString()}");
if (false == document.isValid())
{
err_msg = $"DynamoDbDocument invalid !!! : {document.toBasicString()} - {table.toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbDocumentIsInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, result_documents);
}
var query_type = write_query.getQueryType();
switch (query_type)
{
case QueryType.Insert:
{
transact_write.AddDocumentToPut(document, DynamoDbQueryOperationOptionConfig.getTransactWriteConfigForNotExistKey());
break;
}
case QueryType.Update:
{
transact_write.AddDocumentToUpdate( document, DynamoDbQueryOperationOptionConfig.getTransactWriteConfigForExistKey());
break;
}
case QueryType.Upsert:
{
transact_write.AddDocumentToUpdate( document );
break;
}
case QueryType.Delete:
{
transact_write.AddItemToDelete( document );
break;
}
case QueryType.ExistsDelete:
{
transact_write.AddItemToDelete( document, DynamoDbQueryOperationOptionConfig.getTransactWriteConfigForExistKey());
break;
}
default:
err_msg = $"Invalid QueryType getQueryType() !!! : queryType:{query_type} - {write_query.toBasicString()}, {document.toBasicString()}, {table.toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbDocumentQueryContextTypeInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, result_documents);
}
}
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleTransactWriteWithDocument() !!! : errorCode:{error_code}, exception:{e}, {toWriteTransactQueries.toBasicStringAll()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, result_documents);
}
// 기본(1) + retryCount 만큼 처리 한다. - kangms
for (int i = 0; i <= retryCount; ++i)
{
if (i >= 1)
{
await Task.Delay(2000);
}
try
{
await transact_write.executeAsyncWithStopwatch(eventTid);
}
catch (TransactionCanceledException e)
{
var error_code = ServerErrorCode.DynamoDbTransactionCanceledException;
err_msg = $"TransactionCanceledException !!!, Failed to perfom in simpleTransactWriteWithDocument() !!! : Transaction Canceled, implies a client issue, fix before retrying !!! : errorCode:{error_code}, exception:{e.toExceptionString()}, {toWriteTransactQueries.toBasicStringAll()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
catch (TransactionConflictException e)
{
var error_code = ServerErrorCode.DynamoDbTransactionConflictException;
err_msg = $"TransactionConflictException !!!, Failed to perfom in simpleTransactWriteWithDocument() !!! : Transaction conflict occurred !!! : errorCode:{error_code}, {e.toExceptionString()}, {toWriteTransactQueries.toBasicStringAll()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
catch (AmazonDynamoDBException e)
{
var error_code = ServerErrorCode.DynamoDbAmazonDynamoDbException;
err_msg = $"AmazonDynamoDBException !!!, Failed to perfom in simpleTransactWriteWithDocument() !!! : errorCode:{error_code}, {e.toExceptionString()}, {toWriteTransactQueries.toBasicStringAll()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
catch (AmazonServiceException e)
{
var error_code = ServerErrorCode.DynamoDbAmazonServiceException;
err_msg = $"AmazonServiceException !!!, Failed to perfom in simpleTransactWriteWithDocument() !!! : errorCode:{error_code}, {e.toExceptionString()}, {toWriteTransactQueries.toBasicStringAll()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
continue;
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perfom in simpleTransactWriteWithDocument() !!! : errorCode:{error_code}, exception:{e}, {toWriteTransactQueries.toBasicStringAll()} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
return (result, result_documents);
}
return (result, result_documents);
}
public static async Task<(Result, Dictionary<DYNAMO_DB_TABLE_NAME, List<Document>>)> simpleTransactReadByItemRequestWithDocument( this DynamoDbClient dynamoDbClient
, List<TransactGetItem> toReadTransactQueries
, bool isFailOnEmptyData = false
, UInt16 retryCount = 3 )
{
var result = new Result();
var err_msg = string.Empty;
var read_documents = new Dictionary<DYNAMO_DB_TABLE_FULL_NAME, List<Document>>();
var dynamo_db_connector = dynamoDbClient.getDbClient();
NullReferenceCheckHelper.throwIfNull(dynamo_db_connector, () => $"dynamo_db_connector is null !!! - {toReadTransactQueries.toBasicStringAll()}");
var transact_get = new TransactGetItemsRequest();
try
{
foreach(var get_item in toReadTransactQueries)
{
transact_get.TransactItems.Add(get_item);
}
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleTransactReadByItemRequestWithDocument() !!! : errorCode:{error_code}, exception:{e}, {toReadTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, read_documents);
}
// 기본(1) + retryCount 만큼 처리 한다. - kangms
for (int i = 0; i <= retryCount; ++i)
{
if (i >= 1)
{
await Task.Delay(2000);
}
try
{
var db_response = await dynamo_db_connector.TransactGetItemsAsync(transact_get);
for (var k = 0; k < transact_get.TransactItems.Count; k++)
{
var table_name = transact_get.TransactItems[k].Get.TableName;
var item_response = db_response.Responses[k];
if(false == read_documents.TryGetValue(table_name, out var documents))
{
documents = new List<Document>();
read_documents.Add(table_name, documents);
}
documents.Add(Document.FromAttributeMap(item_response.Item));
}
if (0 >= read_documents.Count && true == isFailOnEmptyData)
{
result.setFail(ServerErrorCode.DynamoDbQueryNoMatchAttribute, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, read_documents);
}
}
catch (TransactionConflictException e)
{
var error_code = ServerErrorCode.DynamoDbTransactionConflictException;
err_msg = $"TransactionConflictException !!!, Failed to perform in simpleTransactReadByItemRequestWithDocument() !!! : errorCode:{error_code}, exception:{e}, {toReadTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
continue;
}
catch (TransactionCanceledException e)
{
var error_code = ServerErrorCode.DynamoDbTransactionCanceledException;
err_msg = $"TransactionCanceledException !!!, Failed to perform in simpleTransactReadByItemRequestWithDocument() !!! : errorCode:{error_code}, exception:{e}, {toReadTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
continue;
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleTransactReadByItemRequestWithDocument() !!! : errorCode:{error_code}, exception:{e}, {toReadTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
continue;
}
return (result, read_documents);
}
return (result, read_documents);
}
public static async Task<(Result, Dictionary<DYNAMO_DB_TABLE_NAME, List<Document>>)> simpleTransactWriteOfItemRequestWithDocument( this DynamoDbClient dynamoDbClient
, List<DynamoDbDocumentQueryContext> toWriteTransactQueries
, UInt16 retryCount = 3 )
{
var result = new Result();
var err_msg = string.Empty;
var result_documents = new Dictionary<DYNAMO_DB_TABLE_NAME, List<Document>>();
var dynamo_db_connector = dynamoDbClient.getDbClient();
NullReferenceCheckHelper.throwIfNull(dynamo_db_connector, () => $"dynamo_db_connector is null !!! - {toWriteTransactQueries.toBasicStringAll()}");
var transact_write = new TransactWriteItemsRequest();
try
{
foreach (var query_context in toWriteTransactQueries)
{
if (false == query_context.isValid())
{
err_msg = $"DynamoDbDocumentQueryContext invalid !!! - {query_context.toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbDocumentIsNullInQueryContext, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, result_documents);
}
var document = query_context.getDocument();
NullReferenceCheckHelper.throwIfNull(document, () => $"document is null !!!");
if (false == document.isValid())
{
err_msg = $"DynamoDbDocument invalid !!! : {document.toBasicString()} - {query_context.toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbDocumentIsInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, result_documents);
}
var table_full_name = query_context.getTableFullName();
var not_exist_transact_config = DynamoDbQueryOperationOptionConfig.getTransactWriteConfigForNotExistKey();
var exist_transact_config = DynamoDbQueryOperationOptionConfig.getTransactWriteConfigForExistKey();
switch (query_context.getQueryType())
{
case QueryType.Insert:
{
var transact_write_item = new TransactWriteItem()
{
Put = new Put()
{
TableName = table_full_name,
Item = document.ToAttributeMap(),
ReturnValuesOnConditionCheckFailure = Amazon.DynamoDBv2.ReturnValuesOnConditionCheckFailure.ALL_OLD,
},
};
transact_write_item.Put.ConditionExpression = not_exist_transact_config.ConditionalExpression.ExpressionStatement;
transact_write_item.Put.ExpressionAttributeNames[$"#{PrimaryKey.PK_Define}"] = PrimaryKey.PK_Define;
transact_write_item.Put.ExpressionAttributeNames[$"#{PrimaryKey.SK_Define}"] = PrimaryKey.SK_Define;
transact_write.TransactItems.Add(transact_write_item);
break;
}
case QueryType.Update:
{
var keys = document.keysToAttributeMap();
var transact_write_item = new TransactWriteItem()
{
Update = new Update()
{
TableName = table_full_name,
Key = keys,
ExpressionAttributeNames = document.toAttributeNames(),
ExpressionAttributeValues = document.toAttributeValues(),
ReturnValuesOnConditionCheckFailure = Amazon.DynamoDBv2.ReturnValuesOnConditionCheckFailure.ALL_OLD,
}
};
transact_write_item.Update.ConditionExpression = exist_transact_config.ConditionalExpression.ExpressionStatement;
transact_write_item.Update.ExpressionAttributeNames[$"#{PrimaryKey.PK_Define}"] = PrimaryKey.PK_Define;
transact_write_item.Update.ExpressionAttributeNames[$"#{PrimaryKey.SK_Define}"] = PrimaryKey.SK_Define;
transact_write.TransactItems.Add(transact_write_item);
break;
}
case QueryType.Upsert:
{
var keys = document.keysToAttributeMap();
var transact_write_item = new TransactWriteItem()
{
Update = new Update()
{
TableName = table_full_name,
Key = keys,
ExpressionAttributeNames = document.toAttributeNames(),
ExpressionAttributeValues = document.toAttributeValues(),
ReturnValuesOnConditionCheckFailure = Amazon.DynamoDBv2.ReturnValuesOnConditionCheckFailure.ALL_OLD,
}
};
transact_write.TransactItems.Add(transact_write_item);
break;
}
case QueryType.Delete:
{
var keys = document.keysToAttributeMap();
var transact_write_item = new TransactWriteItem()
{
Delete = new Delete()
{
TableName = table_full_name,
Key = keys,
ReturnValuesOnConditionCheckFailure = Amazon.DynamoDBv2.ReturnValuesOnConditionCheckFailure.ALL_OLD,
}
};
transact_write_item.Delete.ConditionExpression = exist_transact_config.ConditionalExpression.ExpressionStatement;
transact_write_item.Delete.ExpressionAttributeNames[$"#{PrimaryKey.PK_Define}"] = PrimaryKey.PK_Define;
transact_write_item.Delete.ExpressionAttributeNames[$"#{PrimaryKey.SK_Define}"] = PrimaryKey.SK_Define;
transact_write.TransactItems.Add(transact_write_item);
break;
}
default:
err_msg = $"Invalid QueryType getQueryType() !!! : {query_context.toBasicString()} - {document.toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbDocumentQueryContextTypeInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, result_documents);
}
}
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perfom in simpleTransactWriteOfItemRequestWithDocument() !!! : errorCode:{error_code}, exception:{e}, {toWriteTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
return (result, result_documents);
}
// 기본(1) + retryCount 만큼 처리 한다. - kangms
for (int i = 0; i <= retryCount; ++i)
{
if (i >= 1)
{
await Task.Delay(2000);
}
try
{
var db_response = await dynamo_db_connector.TransactWriteItemsAsync(transact_write);
if(null != db_response)
{
var responses = db_response.ItemCollectionMetrics;
foreach (var each in responses)
{
var table_name = each.Key;
var collection_metrics = each.Value;
foreach (var item_response in collection_metrics)
{
if (item_response.ItemCollectionKey != null && item_response.ItemCollectionKey.Count > 0)
{
if (false == result_documents.TryGetValue(table_name, out var documents))
{
documents = new List<Document>();
result_documents.Add(table_name, documents);
}
documents.Add(Document.FromAttributeMap(item_response.ItemCollectionKey));
}
}
}
}
}
catch (TransactionCanceledException e)
{
var error_code = ServerErrorCode.DynamoDbTransactionCanceledException;
err_msg = $"TransactionCanceledException !!!, Failed to perfom in simpleTransactWriteOfItemRequestWithDocument() !!!, Transaction Canceled, implies a client issue, fix before retrying !!! : errorCode:{error_code}, {e.toExceptionString()}, {toWriteTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
catch (TransactionConflictException e)
{
var error_code = ServerErrorCode.DynamoDbTransactionConflictException;
err_msg = $"TransactionConflictException !!!, Failed to perfom in simpleTransactWriteOfItemRequestWithDocument() !!!, Transaction conflict occurred !!! : errorCode:{error_code}, {e.toExceptionString()}, {toWriteTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
catch (AmazonDynamoDBException e)
{
var error_code = ServerErrorCode.DynamoDbAmazonDynamoDbException;
err_msg = $"AmazonDynamoDBException !!!, Failed to perfom in simpleTransactWriteOfItemRequestWithDocument() !!! : errorCode:{error_code}, {e.toExceptionString()}, {toWriteTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
catch (AmazonServiceException e)
{
var error_code = ServerErrorCode.DynamoDbAmazonServiceException;
err_msg = $"AmazonServiceException !!!, Failed to perfom in simpleTransactWriteOfItemRequestWithDocument() !!! : errorCode:{error_code}, {e.toExceptionString()}, {toWriteTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
continue;
}
catch (Exception e)
{
var error_code = ServerErrorCode.TryCatchException;
err_msg = $"Exception !!!, Failed to perfom in simpleTransactWriteOfItemRequestWithDocument() !!! : : errorCode:{error_code}, exception:{e}, {toWriteTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
return (result, result_documents);
}
return (result, result_documents);
}
public static async Task<(Result, Dictionary<DYNAMO_DB_TABLE_NAME, List<Document>>)> simpleTransactReadOfItemRequestWithItemRequest( this DynamoDbClient dynamoDbClient
, List<TransactGetItem> toReadTransactQueries
, bool isFailOnEmptyData = false
, UInt16 retryCount = 3)
{
var result = new Result();
var err_msg = string.Empty;
var dynamo_db_connector = dynamoDbClient.getDbClient();
NullReferenceCheckHelper.throwIfNull(dynamo_db_connector, () => $"dynamo_db_connector is null !!! - {toReadTransactQueries.toBasicStringAll()}");
var read_documents = new Dictionary<DYNAMO_DB_TABLE_NAME, List<Document>>();
var transact_get = new TransactGetItemsRequest();
try
{
foreach (var get_item in toReadTransactQueries)
{
transact_get.TransactItems.Add(get_item);
}
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleTransactReadOfItemRequestWithItemRequest() !!! : errorCode:{error_code}, exception:{e}, {toReadTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, read_documents);
}
// 기본(1) + retryCount 만큼 처리 한다. - kangms
for (int i = 0; i <= retryCount; ++i)
{
if (i >= 1)
{
await Task.Delay(2000);
}
try
{
var db_response = await dynamo_db_connector.TransactGetItemsAsync(transact_get);
for (var k = 0; k < transact_get.TransactItems.Count; k++)
{
var table_name = transact_get.TransactItems[k].Get.TableName;
var item_response = db_response.Responses[k];
if (false == read_documents.TryGetValue(table_name, out var documents))
{
documents = new List<Document>();
read_documents.Add(table_name, documents);
}
documents.Add(Document.FromAttributeMap(item_response.Item));
}
if (0 >= read_documents.Count && true == isFailOnEmptyData)
{
result.setFail(ServerErrorCode.DynamoDbQueryNoMatchAttribute, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, read_documents);
}
}
catch (TransactionCanceledException e)
{
var error_code = ServerErrorCode.DynamoDbTransactionCanceledException;
err_msg = $"TransactionCanceledException !!!, Failed to perform in simpleTransactReadOfItemRequestWithItemRequest() !!!, Transaction Canceled, implies a client issue, fix before retrying !!! : errorCode:{error_code}, {e.toExceptionString()}, {toReadTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
catch (TransactionConflictException e)
{
var error_code = ServerErrorCode.DynamoDbTransactionConflictException;
err_msg = $"TransactionConflictException !!!, Failed to perform in simpleTransactReadOfItemRequestWithItemRequest() !!!, Transaction conflict occurred !!! : errorCode:{error_code}, {e.toExceptionString()}, {toReadTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
catch (AmazonDynamoDBException e)
{
var error_code = ServerErrorCode.DynamoDbAmazonDynamoDbException;
err_msg = $"AmazonDynamoDBException !!!, Failed to perform in simpleTransactReadOfItemRequestWithItemRequest() !!! : errorCode:{error_code}, {e.toExceptionString()}, {toReadTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
catch (AmazonServiceException e)
{
var error_code = ServerErrorCode.DynamoDbAmazonServiceException;
err_msg = $"AmazonServiceException !!!, Failed to perform in simpleTransactReadOfItemRequestWithItemRequest() !!! : errorCode:{error_code}, {e.toExceptionString()}, {toReadTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
continue;
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleTransactReadOfItemRequestWithItemRequest() !!! : errorCode:{error_code}, exception:{e}, {toReadTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
return (result, read_documents);
}
return (result, read_documents);
}
public static async Task<(Result, Dictionary<DYNAMO_DB_TABLE_NAME, List<Document>>)> simpleTransactWriteOfItemRequestWithItemRequest( this DynamoDbClient dynamoDbClient
, List<AmazonDynamoDBRequest> toWriteTransactQueries
, UInt16 retryCount = 3)
{
var result = new Result();
var err_msg = string.Empty;
var dynamo_db_connector = dynamoDbClient.getDbClient();
NullReferenceCheckHelper.throwIfNull(dynamo_db_connector, () => $"dynamo_db_connector is null !!! - {toWriteTransactQueries.toBasicStringAll()}");
var result_documents = new Dictionary<DYNAMO_DB_TABLE_NAME, List<Document>>();
var transact_write = new TransactWriteItemsRequest();
try
{
foreach (var request in toWriteTransactQueries)
{
var transact_write_item = new TransactWriteItem();
if(request is PutItemRequest put_request)
{
var put = new Put();
put.TableName = put_request.TableName;
put.Item = put_request.Item;
put.ConditionExpression = put_request.ConditionExpression;
put.ExpressionAttributeNames = put_request.ExpressionAttributeNames;
put.ExpressionAttributeValues = put_request.ExpressionAttributeValues;
put.ReturnValuesOnConditionCheckFailure = Amazon.DynamoDBv2.ReturnValuesOnConditionCheckFailure.ALL_OLD;
put.fillupTimestamps();
transact_write_item.Put = put;
}
else if (request is UpdateItemRequest update_request)
{
var update = new Update();
update.TableName = update_request.TableName;
update.Key = update_request.Key;
update.ExpressionAttributeNames = update_request.ExpressionAttributeNames;
update.ExpressionAttributeValues = update_request.ExpressionAttributeValues;
update.ConditionExpression = update_request.ConditionExpression;
update.UpdateExpression = update_request.UpdateExpression;
update.ReturnValuesOnConditionCheckFailure = Amazon.DynamoDBv2.ReturnValuesOnConditionCheckFailure.ALL_OLD;
var timestamps_result = update.tryFillupTimestamps();
if(timestamps_result.isFail())
{
Log.getLogger().error($"Failed to tryFillupTimestamps() !!!, in simpleTransactWriteOfItemRequestWithItemRequest() !!! : {timestamps_result.toBasicString()}");
}
transact_write_item.Update = update;
}
else if((request is DeleteItemRequest delete_request))
{
var delete = new Delete();
delete.TableName = delete_request.TableName;
delete.Key = delete_request.Key;
delete.ReturnValuesOnConditionCheckFailure = Amazon.DynamoDBv2.ReturnValuesOnConditionCheckFailure.ALL_OLD;
transact_write_item.Delete = delete;
}
else
{
err_msg = $"Invalid dbRequest of AmazonDynamoDBRequest !!! : dbRequest:{request.toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbRequestInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, result_documents);
}
transact_write.TransactItems.Add(transact_write_item);
}
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleTransactWriteOfItemRequestWithItemRequest() !!! : errorCode:{error_code}, exception:{e}, {toWriteTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
return (result, result_documents);
}
// 기본(1) + retryCount 만큼 처리 한다. - kangms
for (int i = 0; i <= retryCount; ++i)
{
if (i >= 1)
{
await Task.Delay(2000);
}
try
{
var db_response = await dynamo_db_connector.TransactWriteItemsAsync(transact_write);
if (null != db_response)
{
var responses = db_response.ItemCollectionMetrics;
foreach (var each in responses)
{
var table_name = each.Key;
var collection_metrics = each.Value;
foreach (var item_response in collection_metrics)
{
if (item_response.ItemCollectionKey != null && item_response.ItemCollectionKey.Count > 0)
{
if (false == result_documents.TryGetValue(table_name, out var documents))
{
documents = new List<Document>();
result_documents.Add(table_name, documents);
}
documents.Add(Document.FromAttributeMap(item_response.ItemCollectionKey));
}
}
}
}
}
catch (TransactionCanceledException e)
{
var error_code = ServerErrorCode.DynamoDbTransactionCanceledException;
err_msg = $"TransactionCanceledException !!!, Failed to perform in simpleTransactWriteOfItemRequestWithItemRequest() !!!, Transaction Canceled, implies a client issue, fix before retrying !!! : errorCode:{error_code}, {e.toExceptionString()}, {toWriteTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
catch (TransactionConflictException e)
{
var error_code = ServerErrorCode.DynamoDbTransactionConflictException;
err_msg = $"TransactionConflictException !!!, Failed to perform in simpleTransactWriteOfItemRequestWithItemRequest() !!!, Transaction conflict occurred !!! : errorCode:{error_code}, {e.toExceptionString()}, {toWriteTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
catch (AmazonDynamoDBException e)
{
var error_code = ServerErrorCode.DynamoDbAmazonDynamoDbException;
err_msg = $"AmazonDynamoDBException !!!, Failed to perform in simpleTransactWriteOfItemRequestWithItemRequest() !!! : errorCode:{error_code}, {e.toExceptionString()}, {toWriteTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
catch (AmazonServiceException e)
{
var error_code = ServerErrorCode.DynamoDbAmazonServiceException;
err_msg = $"AmazonServiceException !!!, Failed to perform in simpleTransactWriteOfItemRequestWithItemRequest() !!! : errorCode:{error_code}, {e.toExceptionString()}, {toWriteTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
continue;
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbException;
err_msg = $"Exception !!!, Failed to perform in simpleTransactWriteOfItemRequestWithItemRequest() !!! : errorCode:{error_code}, exception:{e}, {toWriteTransactQueries.toBasicStringAll()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
break;
}
return (result, result_documents);
}
return (result, result_documents);
}
//=========================================================================================
// UpdateItemRequest 기반 간단한 쿼리 실행 하기
//=========================================================================================
public static async Task<(Result, Document?)> simpleQueryWithUpdateItemRequest( this DynamoDbClient dynamoDbClient
, UpdateItemRequest updateItemRequest, bool isUpsert = false, string eventTid ="")
{
var result = new Result();
var err_msg = string.Empty;
Document? updated_doc;
try
{
updateItemRequest.ReturnValues = "ALL_NEW";
var dynamo_db_connector = dynamoDbClient.getDbClient();
NullReferenceCheckHelper.throwIfNull(dynamo_db_connector, () => $"dynamo_db_connector is null !!! - {updateItemRequest.toBasicString()}");
result = updateItemRequest.tryFillupTimestamps(isUpsert);
if(result.isFail())
{
return (result, null);
}
var response = await dynamo_db_connector.updateItemAsyncWithStopwatch(updateItemRequest, eventTid);
var updated_item = response.Attributes;
updated_doc = Document.FromAttributeMap(updated_item);
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbQueryException;
err_msg = $"Exception !!!, Failed to perform in simpleQueryWithUpdateItemRequest() !!! : errorCode:{error_code}, exception:{e}, {updateItemRequest.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
return (result, null);
}
return (result, updated_doc);
}
//=========================================================================================
// 스캔 기반 검색 설정 만들어 반환 하기
//=========================================================================================
public static ScanOperationConfig makeScanConfigWithPKByPKBeginWith(this DynamoDbClient dynamoDbClient, string pk)
{
var filter = new ScanFilter();
filter.AddCondition("PK", ScanOperator.BeginsWith, pk);
var config = new ScanOperationConfig()
{
Filter = filter,
ConsistentRead = true
};
return config;
}
//=========================================================================================
// 스캔 기반 검색 : 호출시 DB 성능 저하 주의, 서버 테스트 목적으로 사용 고려
//=========================================================================================
public static async Task<(Result, List<Document>)> simpleScanWithScanOperationConfig(this Table table, ScanOperationConfig scanOperationConfig)
{
var result = new Result();
var err_msg = string.Empty;
var documents = new List<Document>();
try
{
var search = table.Scan(scanOperationConfig);
while (search.IsDone == false)
{
var next_documents = await search.GetNextSetAsync();
if (null == next_documents)
{
return (result, documents);
}
foreach (var document in next_documents)
{
documents.Add(document);
}
}
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbQueryException;
err_msg = $"Exception !!!, Failed to perform in simpleScanWithScanOperationConfig() !!! : errorCode:{error_code}, exception:{e} - {table.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(err_msg);
return (result, documents);
}
return (result, documents);
}
public static async Task<(Result, bool)> isExistPrimaryKey( this DynamoDbClient dynamoDbClient
, DYNAMO_DB_TABLE_NAME tableName, PrimaryKey primaryKey
, bool isFailOnEmptyData = false
, bool isConsistentRead = false )
{
var result = new Result();
var err_msg = string.Empty;
if (tableName.isNullOrWhiteSpace())
{
err_msg = $"Invalid TableName of DynamoDb !!!, Null of WhiteSpace : tableName:{tableName} - {primaryKey.toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbTableNameInvalid, err_msg);
return (result, false);
}
var dynamo_db_connector = dynamoDbClient.getDbClient();
NullReferenceCheckHelper.throwIfNull(dynamo_db_connector, () => $"dynamo_db_connector is null !!! - {primaryKey.toBasicString()}, tableName:{tableName}");
// GetItemRequest 설정
var get_request = new GetItemRequest
{
TableName = tableName,
Key = primaryKey.toKeyWithAttributeValue(),
ProjectionExpression = $"{PrimaryKey.PK_Define},{PrimaryKey.SK_Define}",
ConsistentRead = isConsistentRead // 일관된 읽기를 사용하지 않음 (성능 최적화)
};
try
{
var response = await dynamo_db_connector.GetItemAsync(get_request);
if (false == response.IsItemSet)
{
err_msg = $"Not found PrimaryKey in DynamoDb !!! : {primaryKey.toBasicString()}, tableName:{tableName}";
if (true == isFailOnEmptyData)
{
result.setFail(ServerErrorCode.DynamoDbQueryNoMatchAttribute, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, false);
}
Log.getLogger().warn(err_msg);
return (result, false);
}
}
catch (Exception e)
{
var error_code = ServerErrorCode.DynamoDbQueryException;
err_msg = $"Exception !!!, Failed to perform in isExistPrimaryKey() !!! : errorCode:{error_code}, exception:{e}, {primaryKey.toBasicString()}, tableName:{tableName}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, false);
}
return (result, true);
}
//=========================================================================================
// Document => AmazonDynamoDBRequest 변환해 준다.
//=========================================================================================
public static (Result, DynamoDbItemRequestQueryContext?) toItemRequestQueryContext( this Amazon.DynamoDBv2.DocumentModel.Document document
, DYNAMO_DB_TABLE_FULL_NAME tableFullName, QueryType queryType )
{
var result = new Result();
var err_msg = string.Empty;
if (tableFullName.isNullOrWhiteSpace())
{
err_msg = $"Invalid TableFullName of DynamoDb !!!, Null of WhiteSpace : tableFullName:{tableFullName}, QueryType:{queryType} - {document.toBasicString()}";
result.setFail(ServerErrorCode.DynamoDbTableNameInvalid, err_msg);
return (result, null);
}
(result, var primary_key) = document.toPrimaryKey();
if(result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(primary_key, () => $"primary_key is null !!! : {document.toBasicString()} - QueryType:{queryType}, tableFullName:{tableFullName}");
DynamoDbItemRequestQueryContext? item_request_query_context;
switch (queryType)
{
case QueryType.Insert:
{
var to_insert_query_builder = new DynamoDbItemRequestHelper.PutItemRequestBuilder(tableFullName);
to_insert_query_builder.withItem(document.ToAttributeMap());
item_request_query_context = new DynamoDbItemRequestQueryContext(to_insert_query_builder.build(), queryType);
} break;
case QueryType.Update:
{
var to_update_query_builder = new DynamoDbItemRequestHelper.UpdateItemRequestBuilder(tableFullName);
to_update_query_builder.withKeys(primary_key.toKeyWithAttributeValue());
to_update_query_builder.withDocument(document);
(result, var update_item_request) = to_update_query_builder.build();
if(result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(update_item_request, () => $"update_item_request is null !!! - QueryType:{queryType}, tableFullName:{tableFullName}");
item_request_query_context = new DynamoDbItemRequestQueryContext(update_item_request, queryType);
} break;
case QueryType.Upsert:
{
var to_upsert_query_builder = new DynamoDbItemRequestHelper.UpdateItemRequestBuilder(tableFullName, true);
to_upsert_query_builder.withKeys(primary_key.toKeyWithAttributeValue());
to_upsert_query_builder.withDocument(document);
(result, var update_item_request) = to_upsert_query_builder.build();
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(update_item_request, () => $"update_item_request is null !!! - QueryType:{queryType}, tableFullName:{tableFullName}");
item_request_query_context = new DynamoDbItemRequestQueryContext(update_item_request, queryType);
} break;
case QueryType.Delete:
{
var to_delete_query_builder = new DynamoDbItemRequestHelper.DeleteItemRequestBuilder(tableFullName);
to_delete_query_builder.withKeys(primary_key.toKeyWithAttributeValue());
item_request_query_context = new DynamoDbItemRequestQueryContext(to_delete_query_builder.build(), queryType);
} break;
default:
err_msg = $"Invalid QueryType !!! : QueryType:{queryType} - {document.toBasicString()}, tableFullName:{tableFullName}";
result.setFail(ServerErrorCode.DbQueryTypeInvalid, err_msg);
return (result, null);
}
return (result, item_request_query_context);
}
//=========================================================================================
// DynamoDbDocBase.ATTRIBUTE_PATH Json 정보 => ExpressionAttributeNames 정보로 변환해 준다.
//=========================================================================================
public static Dictionary<string, string> toExpressionAttributeNamesFromJson(string jsonString, string targetLeafKey)
{
(var is_success, var fillup_key_paths) = maekKeyPathsFromJson(jsonString, targetLeafKey);
var path_parts = fillup_key_paths.Split('.');
return path_parts.Distinct().ToDictionary(part => "#" + part, part => part);
}
//=========================================================================================
// JsonString => AttributeExpression 정보로 변환해 준다.
//=========================================================================================
public static (bool, string) toAttributeExpressionFromJson(string jsonString, string targetLeafKey)
{
(var is_success, var fillup_key_paths) = maekKeyPathsFromJson(jsonString, targetLeafKey);
if(is_success)
{
var parts = fillup_key_paths.Split('.');
for (var i = 0; i < parts.Length; i++)
{
parts[i] = "#" + parts[i];
}
return (true, string.Join(".", parts));
}
return (false, string.Empty);
}
//=========================================================================================
// JsonString => AttributePath 정보로 변환해 준다. (AttributePath : Path.Path.Path ...)
//=========================================================================================
public static (bool, string) maekKeyPathsFromJson(string jsonString, string targetLeafKey)
{
if(true == JsonHelper.fillupKeyPaths(jsonString, targetLeafKey, out var fillup_key_paths))
{
return (true, fillup_key_paths);
}
return (false, string.Empty);
}
public static Dictionary<string, AttributeValue> keysToAttributeMap(this Amazon.DynamoDBv2.DocumentModel.Document document)
{
var key = new Dictionary<string, AttributeValue>();
foreach (var kvp in document)
{
if ( PrimaryKey.PK_Define == kvp.Key
|| PrimaryKey.SK_Define == kvp.Key )
{
key[kvp.Key] = new AttributeValue { S = kvp.Value.AsString() };
}
}
return key;
}
public static Dictionary<string, string> toAttributeNames(this Amazon.DynamoDBv2.DocumentModel.Document document, string? parentPath = null)
{
var attribute_names = new Dictionary<string, string>();
foreach (var kvp in document)
{
if ( kvp.Key != PrimaryKey.PK_Define && kvp.Key != PrimaryKey.SK_Define )
{
string attribute_path = parentPath != null ? $"{parentPath}.{kvp.Key}" : kvp.Key;
string placeholder_name = $"#{attribute_path.Replace('.', '_')}";
string placeholder_value = $":{attribute_path.Replace('.', '_')}";
if (kvp.Value is Document nestedDoc)
{
toAttributeNames(nestedDoc, attribute_path);
}
else if (kvp.Value is Primitive primitiveValue)
{
attribute_names[placeholder_name] = kvp.Key;
}
}
}
return attribute_names;
}
public static Dictionary<string, AttributeValue> toAttributeValues(this Amazon.DynamoDBv2.DocumentModel.Document document, string? parentPath = null)
{
var attribute_values = new Dictionary<string, AttributeValue>();
foreach (var kvp in document)
{
if (kvp.Key != PrimaryKey.PK_Define && kvp.Key != PrimaryKey.SK_Define)
{
string attribute_path = parentPath != null ? $"{parentPath}.{kvp.Key}" : kvp.Key;
string placeholder_value = $":{attribute_path.Replace('.', '_')}";
if (kvp.Value is Document nested_doc)
{
toAttributeValues(nested_doc, attribute_path);
}
else if (kvp.Value is Primitive primitiveValue)
{
attribute_values[placeholder_value] = convertToAttributeValue(placeholder_value);
}
}
}
return attribute_values;
}
public static AttributeValue convertToAttributeValue(Primitive primitive)
{
if (primitive.Type == DynamoDBEntryType.String)
{
return new AttributeValue { S = primitive.AsString() };
}
if (primitive.Type == DynamoDBEntryType.Numeric)
{
return new AttributeValue { N = primitive.AsString() };
}
if (primitive.Type == DynamoDBEntryType.Binary)
{
return new AttributeValue { B = new System.IO.MemoryStream(primitive.AsByteArray()) };
}
throw new InvalidOperationException("Unsupported Primitive type");
}
public static Amazon.DynamoDBv2.DocumentModel.Document classToDynamoDbDocument<T>(T classObject)
{
NullReferenceCheckHelper.throwIfNull(classObject, () => $"classObject is null !!!");
var document = new Amazon.DynamoDBv2.DocumentModel.Document();
var type = classObject.GetType();
foreach (var property in type.GetProperties())
{
string attribute_name = string.Empty;
var json_property = property.GetCustomAttribute<JsonPropertyAttribute>();
if ( null != json_property
&& null != json_property.PropertyName
&& false == json_property.PropertyName.isNullOrWhiteSpace() )
{
attribute_name = json_property.PropertyName;
}
else
{
attribute_name = property.Name;
}
var value = property.GetValue(classObject);
if (value == null)
{
var err_msg = $"Return null is property.GetValue() !!! - attributeName:{attribute_name}";
Log.getLogger().warn(err_msg);
continue;
}
document[attribute_name] = convertToDynamoDBEntry(value);
}
return document;
}
public static Amazon.DynamoDBv2.DocumentModel.DynamoDBEntry convertToDynamoDBEntry(object value)
{
var type = value.GetType();
if (type.isPrimitiveType() && false == type.isBool())
{
return new Primitive(value.ToString(), true);
}
else if(type.isBool() || type.isString() || type.isEnum())
{
return new Primitive(value.ToString());
}
else if (type.isTimestamp())
{
Timestamp timestamp = (Timestamp)value;
DateTime dateTime = timestamp.ToDateTime();
return new Primitive(dateTime.toStringWithUtcIso8601());
}
else if (type.isDateTime())
{
DateTime dateTime = (DateTime)value;
return new Primitive(dateTime.toStringWithUtcIso8601());
}
else if (type.isTimeSpan())
{
TimeSpan timeSpan = (TimeSpan)value;
return new Primitive(timeSpan.ToString("G"));
}
else if (type.isByteArray())
{
return new Primitive((byte[])value);
}
else if (type.isList())
{
var list = value as IList;
NullReferenceCheckHelper.throwIfNull(list, () => $"list is null !!!");
var dynamo_db_list = new DynamoDBList();
foreach (var element in list)
{
dynamo_db_list.Add(convertToDynamoDBEntry(element));
}
return dynamo_db_list;
}
else if (type.isDictionary())
{
var dictionary = value as IDictionary;
NullReferenceCheckHelper.throwIfNull(dictionary, () => $"dictionary is null !!!");
var dynamo_db_dictionary = new Amazon.DynamoDBv2.DocumentModel.Document();
foreach (DictionaryEntry entry in dictionary)
{
NullReferenceCheckHelper.throwIfNull(entry.Value, () => $"entry.Value is null !!!");
dynamo_db_dictionary[entry.Key.ToString()] = convertToDynamoDBEntry(entry.Value);
}
return dynamo_db_dictionary;
}
// Class 타입인 경우 !!!
else
{
return classToDynamoDbDocument(value);
}
}
public static T dynamoDbDocumentToClass<T>(Amazon.DynamoDBv2.DocumentModel.DynamoDBEntry dbEntry)
where T : class, new()
{
return (T) dynamoDbDocumentToObject(dbEntry, typeof(T));
}
public static object dynamoDbDocumentToObject(Amazon.DynamoDBv2.DocumentModel.DynamoDBEntry dbEntry, System.Type toCreateType)
{
// targetType이 string인 경우 빈 문자열로 초기화, 그렇지 않으면 Activator.CreateInstance 사용
object? created_object;
if (toCreateType == typeof(string))
{
created_object = string.Empty;
}
else
{
created_object = Activator.CreateInstance(toCreateType);
NullReferenceCheckHelper.throwIfNull(created_object, () => $"created_object is null !!! - toCreateType:{toCreateType.getTypeName()}");
}
var type = created_object.GetType();
if ( type.isPrimitiveType()
|| type.isString()
|| type.isBool()
|| type.isEnum()
|| type.isDateTime()
|| type.isTimeSpan()
|| type.isByteArray())
{
return dynamoDbEntryToValue(dbEntry, created_object);
}
else if (toCreateType.isList())
{
var argument_type = type.GetGenericArguments()[0];
var list = (IList?)Activator.CreateInstance(typeof(List<>).MakeGenericType(argument_type));
NullReferenceCheckHelper.throwIfNull(list, () => $"list is null !!!");
var list_in_dynamodb = dbEntry as Amazon.DynamoDBv2.DocumentModel.DynamoDBList;
if (null == list_in_dynamodb)
{
var err_msg = $"Failed to cast DynamoDBList from DynamoDB !!!, for List : DynamoDBEntry:{dbEntry.ToString()} - createdObject:{created_object.getTypeName()}";
Log.getLogger().fatal(err_msg);
return list;
}
foreach (var db_entry in list_in_dynamodb.Entries)
{
list.Add(dynamoDbDocumentToObject(db_entry, argument_type));
}
return list;
}
else if (type.isDictionary())
{
var key_Type = type.GetGenericArguments()[0];
var value_type = type.GetGenericArguments()[1];
var dictionary = (IDictionary?)Activator.CreateInstance(typeof(Dictionary<,>).MakeGenericType(key_Type, value_type));
NullReferenceCheckHelper.throwIfNull(dictionary, () => $"dictionary is null !!!");
var dictionary_in_dynamodb = dbEntry as Amazon.DynamoDBv2.DocumentModel.Document;
if (null == dictionary_in_dynamodb)
{
var err_msg = $"Failed to cast Document from DynamoDB !!!, for Dictionary : DynamoDBEntry:{dbEntry.ToString()} - createdObject:{created_object.getTypeName()}";
Log.getLogger().fatal(err_msg);
return dictionary;
}
foreach (var kvp in dictionary_in_dynamodb)
{
object element_key_document = kvp.Key;
if (key_Type.isEnum())
{
try
{
element_key_document = System.Enum.Parse(key_Type, kvp.Key);
}
catch (Exception e)
{
var err_msg = $"Exception !!!, Failed to perform in dynamoDbDocumentToObject() !!! : exception:{e}, KeyOfDictionary:{key_Type.Name} == KeyOfDocument:{element_key_document.getTypeName()} - createdObject:{created_object.getTypeName()}";
Log.getLogger().error(err_msg);
continue;
}
}
dictionary.Add(element_key_document, dynamoDbDocumentToObject(kvp.Value, value_type));
}
return dictionary;
}
else
{
var document_in_dynamodb = dbEntry as Amazon.DynamoDBv2.DocumentModel.Document;
if (null == document_in_dynamodb)
{
var err_msg = $"Failed to cast Document from DynamoDB !!!, for Class : DynamoDBEntry:{dbEntry.ToString()} - createdObject:{created_object.getTypeName()}";
Log.getLogger().fatal(err_msg);
return created_object;
}
var has_properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var property in has_properties)
{
var json_property = property.GetCustomAttribute<JsonPropertyAttribute>();
string attribute_name = string.Empty;
if (null != json_property
&& null != json_property.PropertyName)
{
attribute_name = json_property.PropertyName;
}
else
{
attribute_name = property.Name;
}
if (false == document_in_dynamodb.TryGetValue(attribute_name, out var child_db_entry))
{
var err_msg = $"Not found Child DynamoDBEntry from DynamoDB !!!, for Property : PropertyName:{attribute_name} - createdObject:{created_object.getTypeName()}";
Log.getLogger().warn(err_msg);
continue;
}
property.SetValue(created_object, dynamoDbDocumentToObject(child_db_entry, property.PropertyType));
}
}
return created_object;
}
public static object dynamoDbEntryToValue(Amazon.DynamoDBv2.DocumentModel.DynamoDBEntry dbEntry, object toValue)
{
var targetType = toValue.GetType();
if (dbEntry is Amazon.DynamoDBv2.DocumentModel.Primitive primitive)
{
if (targetType.isPrimitiveType() && !targetType.isBool())
{
if (primitive.Type == DynamoDBEntryType.Numeric)
{
return primitive.toNumericValue(targetType);
}
}
else if (targetType.isString())
{
if (primitive.Type == DynamoDBEntryType.String)
{
return primitive.Value;
}
}
else if (targetType.isBool())
{
if (primitive.Type == DynamoDBEntryType.String)
{
var bool_string = primitive.AsString();
if (bool.TryParse(bool_string, out var bool_value))
{
return bool_value;
}
}
}
else if (targetType.isEnum())
{
if (primitive.Type == DynamoDBEntryType.String)
{
var enum_string = primitive.AsString();
if (true == System.Enum.TryParse(targetType, enum_string, out var enum_value))
{
return enum_value;
}
}
}
else if (targetType.isDateTime())
{
if (primitive.Type == DynamoDBEntryType.String)
{
var date_string = primitive.AsString();
if (true == DateTime.TryParse(date_string, null, System.Globalization.DateTimeStyles.RoundtripKind, out var date_value))
{
return date_value;
}
}
}
else if (targetType.isTimeSpan())
{
if (primitive.Type == DynamoDBEntryType.String)
{
var time_span_string = primitive.AsString();
if (true == TimeSpan.TryParse(time_span_string, out var time_span_value))
{
return time_span_value;
}
}
}
else if (targetType.isByteArray())
{
if (primitive.Type == DynamoDBEntryType.Binary)
{
return primitive.AsByteArray();
}
}
}
var err_msg = $"Invalid Primitive of DynamoDbClientHelper.dynamoDbEntryToValue() !!! : targetType:{targetType.getTypeName()}, DynamoDBEntry:{dbEntry.ToString()}";
Log.getLogger().fatal(err_msg);
throw new TypeAccessException(err_msg);
}
public static bool setNumericValue(this PropertyInfo property, object targetObject, Primitive primitive)
{
var type = property.PropertyType;
if(type.isShort() || type.isInt16())
{
property.SetValue(targetObject, primitive.AsShort());
}
else if (type.isInt() || type.isInt32())
{
property.SetValue(targetObject, primitive.AsInt());
}
else if (type.isLong())
{
property.SetValue(targetObject, primitive.AsLong());
}
else if(type.isUShort() || type.isUInt16())
{
property.SetValue(targetObject, primitive.AsUShort());
}
else if (type.isUInt() || type.isUInt32())
{
property.SetValue(targetObject, primitive.AsUInt());
}
else if (type.isULong())
{
property.SetValue(targetObject, primitive.AsULong());
}
else if (type.isFloat())
{
property.SetValue(targetObject, primitive.AsSingle());
}
else if(type.isDouble())
{
property.SetValue(targetObject, primitive.AsDouble());
}
else
{
var err_msg = $"Invalid PrimitiveType !!!, setNumericValue() : primitive:{type.Name}";
Log.getLogger().warn(err_msg);
return false;
}
return true;
}
public static object toNumericValue( this Primitive primitive, System.Type typeOfValue )
{
var type = typeOfValue;
if(type.isShort() || type.isInt16())
{
return primitive.AsShort();
}
else if (type.isInt() || type.isInt32())
{
return primitive.AsInt();
}
else if (type.isLong())
{
return primitive.AsLong();
}
else if(type.isUShort() || type.isUInt16())
{
return primitive.AsUShort();
}
else if (type.isUInt() || type.isUInt32())
{
return primitive.AsUInt();
}
else if (type.isULong())
{
return primitive.AsULong();
}
else if (type.isFloat())
{
return primitive.AsSingle();
}
else if(type.isDouble())
{
return primitive.AsDouble();
}
else
{
var err_msg = $"Invalid System.Type !!!, toNumericValue() : System.Type:{type.Name}";
Log.getLogger().error(err_msg);
return 0;
}
}
public static bool isJsonEncoded(this DynamoDBEntry dbEntry)
{
if ( dbEntry is Primitive primitive
&& primitive.Type == DynamoDBEntryType.String )
{
var value = primitive.AsString();
try
{
JToken.Parse(value);
return true;
}
catch (JsonReaderException)
{
return false;
}
}
return false;
}
public static bool isNumeric(this DynamoDBEntryType type)
{
if (DynamoDBEntryType.Numeric == type)
{
return true;
}
return false;
}
public static bool isString(this DynamoDBEntryType type)
{
if (DynamoDBEntryType.String == type)
{
return true;
}
return false;
}
public static bool isBinary(this DynamoDBEntryType type)
{
if (DynamoDBEntryType.Binary == type)
{
return true;
}
return false;
}
public static bool isPrimitive(this Amazon.DynamoDBv2.DocumentModel.DynamoDBEntry dbEntry)
{
var primitive = dbEntry as Amazon.DynamoDBv2.DocumentModel.Primitive;
if (null == primitive)
{
return false;
}
return true;
}
public static bool isDocument(this Amazon.DynamoDBv2.DocumentModel.DynamoDBEntry dbEntry)
{
var document = dbEntry as Amazon.DynamoDBv2.DocumentModel.Document;
if (null == document)
{
return false;
}
return true;
}
public static Int64 makeTTLTimeForDynamoDB(DateTime expireDate)
{
// DateTime 객체를 DateTimeOffset 객체로 변환 한다.
var dateTimeOffset = new DateTimeOffset(expireDate);
// 주의 : DynamoDb TTL 요구 사항 !!!
// DateTimeOffset 객체를 현재시간에 Unix 기준시까지 경과된 시간을 초로 변환 (현재시간 ~ 1970년 1월 1일 00:00:00 UTC 까지의 경과시간)
return dateTimeOffset.ToUnixTimeSeconds();
}
public static DYNAMO_DB_TABLE_NAME getTableName(this AmazonDynamoDBRequest dbRequest)
{
var table_name = string.Empty;
switch (dbRequest)
{
case PutItemRequest put: table_name = put.TableName; break;
case UpdateItemRequest update: table_name = update.TableName; break;
case DeleteItemRequest delete: table_name = delete.TableName; break;
case QueryRequest query: table_name = query.TableName; break;
case ScanRequest scan: table_name = scan.TableName; break;
}
ConditionValidCheckHelper.throwIfFalseWithCondition(() => false == table_name.isNullOrWhiteSpace(), () => $"Invalid TableName !!! - {dbRequest.getTypeName()}");
var err_msg = $"Invalid AmazonDynamoDBRequest of DynamoDbClientHelper.getTableName() !!! : dbRequest:{dbRequest.getTypeName()}";
Log.getLogger().fatal(err_msg);
throw new TypeAccessException(err_msg);
}
public static async Task logDetail(this TransactWriteItemsResponse response)
{
await Task.CompletedTask;
var sb = new StringBuilder();
sb.AppendLine($"HTTP Status Code: {response.HttpStatusCode}");
sb.AppendLine($"Request ID: {response.ResponseMetadata.RequestId}");
if (response.HttpStatusCode == HttpStatusCode.OK)
{
sb.AppendLine($"TransactWriteItemsResponse succeeded.");
Log.getLogger().debug(sb.ToString());
}
else
{
sb.AppendLine($"TransactWriteItems did not fully succeed !!!");
Log.getLogger().error(sb.ToString());
}
sb = new StringBuilder();
if (response.ConsumedCapacity != null && response.ConsumedCapacity.Count > 0)
{
sb.AppendLine($"Consumed Capacity:");
foreach (var capacity in response.ConsumedCapacity)
{
sb.AppendLine($"Table: {capacity.TableName}, CapacityUnits: {capacity.CapacityUnits}");
}
}
if (response.ItemCollectionMetrics != null && response.ItemCollectionMetrics.Count > 0)
{
sb.AppendLine($"Item Collection Metrics:");
foreach (var metrics in response.ItemCollectionMetrics)
{
sb.AppendLine($"Table: {metrics.Key}");
foreach (var metric in metrics.Value)
{
sb.AppendLine($"SizeEstimateRangeGB: {string.Join(", ", metric.SizeEstimateRangeGB)}");
}
}
}
Log.getLogger().debug(sb.ToString());
}
public static async Task logDetail(this TransactGetItemsResponse response, TransactGetItemsRequest request)
{
await Task.CompletedTask;
var sb = new StringBuilder();
sb.AppendLine($"HTTP Status Code: {response.HttpStatusCode}");
sb.AppendLine($"Request ID: {response.ResponseMetadata.RequestId}");
if (response.HttpStatusCode == HttpStatusCode.OK)
{
sb.AppendLine("TransactGetItemsResponse succeeded.");
}
else
{
sb.AppendLine("TransactGetItemsResponse did not fully succeed !!!");
}
sb = new StringBuilder();
if (response.ConsumedCapacity != null && response.ConsumedCapacity.Count > 0)
{
sb.AppendLine("Consumed Capacity:");
foreach (var capacity in response.ConsumedCapacity)
{
sb.AppendLine($"Table: {capacity.TableName}, CapacityUnits: {capacity.CapacityUnits}");
}
}
sb.AppendLine("Item Collection Responses:");
if (request.TransactItems != null && request.TransactItems.Count > 0 && response.Responses != null)
{
for (int i = 0; i < response.Responses.Count; i++)
{
var request_item = request.TransactItems[i].Get;
var table_name = request_item.TableName;
var item_response = response.Responses[i];
sb.AppendLine($"Table: {table_name}");
sb.AppendLine(Document.FromAttributeMap(item_response.Item).ToJsonPretty());
}
}
else
{
sb.AppendLine("No items returned.");
}
Log.getLogger().debug(sb.ToString());
}
public static async Task logDetail(this UpdateItemResponse response)
{
await Task.CompletedTask;
var sb = new StringBuilder();
sb.AppendLine($"HTTP Status Code: {response.HttpStatusCode}");
sb.AppendLine($"Request ID: {response.ResponseMetadata.RequestId}");
if (response.HttpStatusCode == HttpStatusCode.OK)
{
sb.AppendLine($"UpdateItemResponse succeeded.");
if (response.Attributes != null && response.Attributes.Count > 0)
{
sb.AppendLine($"Updated Attributes:");
foreach (var attribute in response.Attributes)
{
sb.AppendLine($"{attribute.Key}: {attribute.Value.S ?? attribute.Value.N}");
}
}
Log.getLogger().debug(sb.ToString());
}
else
{
sb.AppendLine($"UpdateItemResponse did not succeed !!!");
Log.getLogger().error(sb.ToString());
}
}
public static async Task logDetail(this BatchWriteItemResponse response)
{
await Task.CompletedTask;
var sb = new StringBuilder();
sb.AppendLine($"HTTP Status Code: {response.HttpStatusCode}");
sb.AppendLine($"Request ID: {response.ResponseMetadata.RequestId}");
if (response.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
sb.AppendLine($"BatchWriteItemResponse succeeded.");
Log.getLogger().debug(sb.ToString());
}
else
{
sb.AppendLine($"BatchWriteItemResponse did not fully succeed !!!");
Log.getLogger().error(sb.ToString());
}
if (response.UnprocessedItems != null && response.UnprocessedItems.Count > 0)
{
sb.AppendLine($"BatchWriteItemResponse Unprocessed Items:");
foreach (var table in response.UnprocessedItems)
{
sb.AppendLine($"Table: {table.Key}");
foreach (var item in table.Value)
{
if (item.PutRequest != null)
{
sb.AppendLine($"Unprocessed PutRequest:");
sb.AppendLine(Document.FromAttributeMap(item.PutRequest.Item).ToJsonPretty());
}
if (item.DeleteRequest != null)
{
sb.AppendLine($"Unprocessed DeleteRequest:");
sb.AppendLine(Document.FromAttributeMap(item.DeleteRequest.Key).ToJsonPretty());
}
}
}
Log.getLogger().error(sb.ToString());
}
}
public static async Task logDetail(this BatchGetItemResponse response)
{
await Task.CompletedTask;
var sb = new StringBuilder();
sb.AppendLine($"HTTP Status Code: {response.HttpStatusCode}");
sb.AppendLine($"Request ID: {response.ResponseMetadata.RequestId}");
if (response.Responses != null && response.Responses.Count > 0)
{
sb.AppendLine($"BatchGetItemResponse succeeded.");
foreach (var table in response.Responses)
{
sb.AppendLine($"Table: {table.Key}");
foreach (var item in table.Value)
{
sb.AppendLine(Document.FromAttributeMap(item).ToJsonPretty());
}
}
Log.getLogger().debug(sb.ToString());
}
else
{
sb.AppendLine("BatchGetItemResponse did not return any items !!!");
Log.getLogger().error(sb.ToString());
}
if (response.UnprocessedKeys != null && response.UnprocessedKeys.Count > 0)
{
sb.AppendLine("BatchGetItemResponse Unprocessed Keys:");
foreach (var table in response.UnprocessedKeys)
{
sb.AppendLine($"Table: {table.Key}");
foreach (var key in table.Value.Keys)
{
sb.AppendLine(Document.FromAttributeMap(key).ToJsonPretty());
}
}
Log.getLogger().error(sb.ToString());
}
}
public static string toBasicStringAll(this TransactGetItemsRequest request)
{
var sb = new StringBuilder();
sb.AppendLine("TransactGetItemsRequest : ");
// TransactItems의 각 항목에 대해 로그 작성
if (request.TransactItems != null && request.TransactItems.Count > 0)
{
int itemCount = 1;
foreach (var transactItem in request.TransactItems)
{
sb.AppendLine($"Item {itemCount++}:");
sb.AppendLine($"TableName: {transactItem.Get.TableName}");
// Key 정보를 AttributeMap 형태로 출력
if (transactItem.Get.Key != null)
{
sb.AppendLine("Key:");
foreach (var key in transactItem.Get.Key)
{
sb.AppendLine($"{key.Key}: {key.Value.ToJson()}");
}
}
else
{
sb.AppendLine("Key: No key provided.");
}
if (transactItem.Get.ProjectionExpression != null)
{
sb.AppendLine($"ProjectionExpression: {transactItem.Get.ProjectionExpression}");
}
else
{
sb.AppendLine("ProjectionExpression: None.");
}
}
}
else
{
sb.AppendLine("No TransactItems found in the request.");
}
return sb.ToString();
}
public static string toBasicStringAll(this List<GetItemRequest> toStringGetItemRequests)
{
var sb = new StringBuilder();
sb.AppendLine($"List<GetItemRequest> : ");
foreach (var db_request in toStringGetItemRequests)
{
sb.AppendLine(db_request.toBasicString());
}
return sb.ToString();
}
public static string toBasicString(this AmazonDynamoDBRequest dbRequest)
{
var sb = new StringBuilder();
sb.AppendLine($"AmazonDynamoDBRequest: {dbRequest.getTypeName()}");
// 각 ItemRequest 별 상세 정보를 구성 한다.
switch (dbRequest)
{
case PutItemRequest putItemRequest:
sb.AppendLine($"TableName: {putItemRequest.TableName}");
sb.AppendLine("Item:");
foreach (var kvp in putItemRequest.Item)
{
sb.AppendLine($" {kvp.Key}: {kvp.Value.S ?? kvp.Value.N ?? kvp.Value.B?.ToString() ?? "null"}");
}
break;
case UpdateItemRequest updateItemRequest:
sb.AppendLine($"TableName: {updateItemRequest.TableName}");
sb.AppendLine($"Key: {getKeyString(updateItemRequest.Key)}");
sb.AppendLine($"ExpressionAttributeNames: {getAttributeNamesString(updateItemRequest.ExpressionAttributeNames)}");
sb.AppendLine($"ExpressionAttributeValues: {getAttributeValuesString(updateItemRequest.ExpressionAttributeValues)}");
sb.AppendLine($"UpdateExpression: {updateItemRequest.UpdateExpression}");
break;
case DeleteItemRequest deleteItemRequest:
sb.AppendLine($"TableName: {deleteItemRequest.TableName}");
sb.AppendLine($"Key: {getKeyString(deleteItemRequest.Key)}");
break;
case QueryRequest queryRequest:
sb.AppendLine($"TableName: {queryRequest.TableName}");
sb.AppendLine($"KeyConditionExpression: {queryRequest.KeyConditionExpression}");
break;
case ScanRequest scanRequest:
sb.AppendLine($"TableName: {scanRequest.TableName}");
sb.AppendLine($"Limit: {scanRequest.Limit}");
break;
default:
sb.AppendLine($"Unknown ItemRequest Type !!! : AmazonDynamoDBRequest:{dbRequest.getTypeName()}");
break;
}
return sb.ToString();
}
public static string toBasicStringAll(this List<AmazonDynamoDBRequest> toStringDbRequests)
{
var sb = new StringBuilder();
sb.AppendLine($"List<DynamoDbDocumentQueryContext> : ");
foreach (var db_request in toStringDbRequests)
{
sb.AppendLine(db_request.toBasicString());
}
return sb.ToString();
}
public static string toBasicStringAll(this List<DynamoDbDocumentQueryContext> toStringQueryContexts)
{
var sb = new StringBuilder();
sb.AppendLine($"List<DynamoDbDocumentQueryContext> : ");
foreach (var query_context in toStringQueryContexts)
{
sb.AppendLine(query_context.toBasicString());
}
return sb.ToString();
}
public static string toBasicStringAll(this List<(PrimaryKey, TransactGetItemOperationConfig?)> toQueryDatas)
{
var sb = new StringBuilder();
sb.AppendLine($"List<(PrimaryKey, TransactGetItemOperationConfig?)> : ");
foreach (var query_data in toQueryDatas)
{
sb.AppendLine(query_data.Item1.toBasicString());
sb.AppendLine(query_data.Item2 != null ? query_data.Item2.toBasicString() : "");
}
return sb.ToString();
}
public static string toBasicString(this TransactGetItemOperationConfig toStringOperationConfig)
{
var sb = new StringBuilder();
sb.AppendLine("TransactGetItemOperationConfig : ");
var value = toStringOperationConfig.ProjectionExpression != null ? toStringOperationConfig.ProjectionExpression.toBasicString() : "";
sb.AppendLine(value);
return sb.ToString();
}
public static string toBasicStringAll(this List<TransactGetItem> toStringGetItems)
{
var sb = new StringBuilder();
sb.AppendLine($"List<TransactGetItem> : ");
foreach (var get_item in toStringGetItems)
{
sb.AppendLine(get_item.Get.toBasicString());
}
return sb.ToString();
}
public static string toBasicString(this Get get)
{
var sb = new StringBuilder();
sb.AppendLine($"TableName: {get.TableName}");
if (get.Key != null && get.Key.Count > 0)
{
sb.AppendLine("Key:");
sb.AppendLine($" {getAttributeValuesString(get.Key)}");
}
if (false == get.ProjectionExpression.isNullOrWhiteSpace())
{
sb.AppendLine($"ProjectionExpression: {get.ProjectionExpression}");
}
if (null != get.ExpressionAttributeNames)
{
sb.AppendLine($"ExpressionAttributeNames: {getAttributeNamesString(get.ExpressionAttributeNames)}");
}
return sb.ToString();
}
public static string toBasicStringAll(this List<Document> documents)
{
var sb = new StringBuilder();
sb.AppendLine($"List<Document> : ");
foreach (var document in documents)
{
sb.AppendLine(document.toBasicString());
}
return sb.ToString();
}
public static string toBasicString(this Document document)
{
return $"document:{document?.ToJsonPretty()}";
}
public static string toBasicString(this Expression expression)
{
var sb = new StringBuilder();
if (expression is Expression projectionExpression)
{
sb.AppendLine("Projection Expression: ");
sb.AppendLine($"Expression: {projectionExpression.ToString()}");
}
else
{
sb.AppendLine("Unknown Expression Type: ");
sb.AppendLine(expression.ToString());
}
return sb.ToString();
}
private static string getKeyString(Dictionary<string, AttributeValue> key)
{
var sb = new StringBuilder();
foreach (var kvp in key)
{
sb.Append($"{kvp.Key}:{kvp.Value.S ?? kvp.Value.N ?? "null"} ");
}
return sb.ToString();
}
private static string getAttributeNamesString(Dictionary<string, string> attributeNames)
{
var sb = new StringBuilder();
foreach (var name in attributeNames)
{
sb.Append($"{name.Key}:{name.Value ?? "null"} ");
}
return sb.ToString();
}
private static string getAttributeValuesString(Dictionary<string, AttributeValue> attributeValues)
{
var sb = new StringBuilder();
foreach (var value in attributeValues)
{
sb.Append($"{value.Key}:{value.Value.S ?? value.Value.N ?? "null"} ");
}
return sb.ToString();
}
public static string toBasicString(this Table table)
{
return $"TableName:{table.TableName}";
}
}