2505 lines
100 KiB
C#
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}";
|
|
}
|
|
} |