1369 lines
54 KiB
C#
1369 lines
54 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Net.WebSockets;
|
|
|
|
|
|
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using Amazon.S3.Model;
|
|
using Amazon.DynamoDBv2.DocumentModel;
|
|
using Amazon.DynamoDBv2.Model;
|
|
using Amazon.DynamoDBv2;
|
|
using Amazon.Runtime.Internal.Transform;
|
|
using Amazon.DynamoDBv2.DataModel;
|
|
using Microsoft.AspNetCore.Components.Web;
|
|
|
|
|
|
using ServerCore; using ServerBase;
|
|
|
|
|
|
|
|
using DYNAMO_DB_TABLE_NAME = System.String;
|
|
using DYNAMO_DB_TABLE_FULL_NAME = System.String;
|
|
using DB_TIMESTAMP = System.String;
|
|
|
|
|
|
namespace ServerBase;
|
|
|
|
public static class DynamoDBDocBaseHelper
|
|
{
|
|
public static async Task<(Result, PrimaryKey?)> makePrimaryKey<TDoc>(string PK, string SK = DynamoDbClient.SK_EMPTY)
|
|
where TDoc : DynamoDbDocBase, new()
|
|
{
|
|
await Task.CompletedTask;
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var doc = new TDoc();
|
|
doc.setCombinationKeyForPKSK(PK, SK);
|
|
var error_code = doc.onApplyPKSK();
|
|
if (error_code.isFail())
|
|
{
|
|
err_msg = $"Failed to onApplyPKSK() !!! : {doc.getPrimaryKey().toBasicString()}, Params(PK:{PK}, SK:{SK}), Doc:{typeof(TDoc).Name}";
|
|
result.setFail(error_code, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, doc.getPrimaryKey());
|
|
}
|
|
|
|
public static Dictionary<string, AttributeValue> toKeyWithAttributeValue(this PrimaryKey primaryKey)
|
|
{
|
|
var key = new Dictionary<string, AttributeValue>
|
|
{
|
|
{
|
|
PrimaryKey.PK_Define
|
|
, new AttributeValue { S = primaryKey.PK }
|
|
}
|
|
,
|
|
{
|
|
PrimaryKey.SK_Define
|
|
, new AttributeValue { S = primaryKey.SK }
|
|
}
|
|
};
|
|
|
|
return key;
|
|
}
|
|
|
|
public static Primitive toPartitionKey(this PrimaryKey primaryKey)
|
|
{
|
|
ConditionValidCheckHelper.throwIfFalseWithCondition( () => false == primaryKey.PK.isNullOrWhiteSpace()
|
|
, () => $"Invalid PK, Null or WhiteSpace !!!" );
|
|
return new Primitive(primaryKey.PK);
|
|
}
|
|
|
|
public static Primitive? toSortKey(this PrimaryKey primaryKey)
|
|
{
|
|
if (true == primaryKey.SK.isNullOrWhiteSpace()) return null;
|
|
return new Primitive(primaryKey.SK);
|
|
}
|
|
|
|
public static Result tryFillupUpdateItemRequest( this Amazon.DynamoDBv2.DocumentModel.Document document
|
|
, UpdateItemRequest updateItemRequest
|
|
, bool isUpsert = false )
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
if (false == document.isValid())
|
|
{
|
|
err_msg = $"DynamoDbDocument invalid !!! : {document.toBasicString()}";
|
|
result.setFail(ServerErrorCode.DynamoDbDocumentIsInvalid, err_msg);
|
|
|
|
return result;
|
|
}
|
|
|
|
var update_expression = "SET ";
|
|
var expression_attribute_names = new Dictionary<string, string>();
|
|
var expression_attribute_values = new Dictionary<string, AttributeValue>();
|
|
|
|
var expression_idx = 0;
|
|
foreach ( var each in document.ToAttributeMap() )
|
|
{
|
|
if( each.Key == PrimaryKey.PK_Define
|
|
|| each.Key == PrimaryKey.SK_Define )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (expression_idx > 0)
|
|
{
|
|
update_expression += ", ";
|
|
}
|
|
|
|
var placeholder_key = $"#{each.Key}";
|
|
var placeholder_value = $":{each.Key}";
|
|
|
|
update_expression += $"{placeholder_key} = {placeholder_value}";
|
|
|
|
expression_idx++;
|
|
|
|
expression_attribute_names.Add(placeholder_key, each.Key);
|
|
expression_attribute_values.Add(placeholder_value, each.Value);
|
|
}
|
|
|
|
updateItemRequest.UpdateExpression = update_expression;
|
|
updateItemRequest.ExpressionAttributeNames = expression_attribute_names;
|
|
updateItemRequest.ExpressionAttributeValues = expression_attribute_values;
|
|
updateItemRequest.ReturnValues = "ALL_NEW";
|
|
|
|
if( false == isUpsert
|
|
&& null != updateItemRequest.ConditionExpression
|
|
&& true == updateItemRequest.ConditionExpression.isNullOrWhiteSpace() )
|
|
{
|
|
updateItemRequest.ConditionExpression = $"attribute_exists({PrimaryKey.PK_Define}) AND attribute_exists({PrimaryKey.SK_Define})";
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static async Task<Result> tryFillupTimestampsForUpsert( this Document document
|
|
, DynamoDbClient dynamoDbClient, DYNAMO_DB_TABLE_NAME tableName)
|
|
{
|
|
var result = new Result();
|
|
|
|
(result, bool is_found) = await dynamoDbClient.checkIfDocumentExists(tableName, document);
|
|
if(result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
// 데이터가 존재하는 경우
|
|
if(true == is_found)
|
|
{
|
|
result = document.tryFillupTimestamps(QueryType.Update);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
// 데이터가 없는 경우
|
|
else
|
|
{
|
|
result = document.tryFillupTimestamps(QueryType.Insert);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static void fillupTimestamps(this Amazon.DynamoDBv2.Model.Put put)
|
|
{
|
|
var attribute_values = put.Item;
|
|
NullReferenceCheckHelper.throwIfNull(attribute_values, () => $"attributes is null !!!");
|
|
|
|
fillupAttributeValueWithTimestampsForInsert(attribute_values, DateTimeHelper.Current);
|
|
}
|
|
|
|
public static Result tryFillupTimestamps(this Amazon.DynamoDBv2.Model.Update update, bool isUpsert = false)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var statement = update.UpdateExpression;
|
|
NullReferenceCheckHelper.throwIfNull(statement, () => $"attribute_names is null !!!");
|
|
var attribute_names = update.ExpressionAttributeNames;
|
|
NullReferenceCheckHelper.throwIfNull(attribute_names, () => $"attribute_names is null !!!");
|
|
var attribute_values = update.ExpressionAttributeValues;
|
|
NullReferenceCheckHelper.throwIfNull(attribute_values, () => $"attribute_values is null !!!");
|
|
|
|
result = tryFillupTimestamps( ref statement
|
|
, attribute_names, attribute_values
|
|
, DateTimeHelper.Current
|
|
, isUpsert );
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
update.UpdateExpression = statement;
|
|
|
|
return result;
|
|
}
|
|
|
|
public static Result tryFillupTimestamps(this Amazon.DynamoDBv2.DocumentModel.Expression expression, bool isUpsert = false)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var statement = expression.ExpressionStatement;
|
|
NullReferenceCheckHelper.throwIfNull(statement, () => $"statement is null !!!");
|
|
var attribute_names = expression.ExpressionAttributeNames;
|
|
NullReferenceCheckHelper.throwIfNull(attribute_names, () => $"attribute_names is null !!!");
|
|
var attribute_values = expression.ExpressionAttributeValues;
|
|
NullReferenceCheckHelper.throwIfNull(attribute_values, () => $"attribute_values is null !!!");
|
|
|
|
result = tryFillupTimestamps( ref statement
|
|
, attribute_names, attribute_values
|
|
, DateTimeHelper.Current
|
|
, isUpsert );
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
expression.ExpressionStatement = statement;
|
|
|
|
return result;
|
|
}
|
|
|
|
public static void fillupTimestamps(this PutItemRequest putItemRequest)
|
|
{
|
|
var attributes = putItemRequest.Item;
|
|
NullReferenceCheckHelper.throwIfNull(attributes, () => $"attributes is null !!!");
|
|
|
|
fillupAttributeValueWithTimestampsForInsert(attributes, DateTimeHelper.Current);
|
|
}
|
|
|
|
public static Result tryFillupTimestamps(this UpdateItemRequest updateItemRequest, bool isUpsert = false)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var statement = updateItemRequest.UpdateExpression;
|
|
NullReferenceCheckHelper.throwIfNull(statement, () => $"statement is null !!! - {updateItemRequest.toBasicString()}");
|
|
var attribute_names = updateItemRequest.ExpressionAttributeNames;
|
|
NullReferenceCheckHelper.throwIfNull(attribute_names, () => $"attribute_names is null !!! - {updateItemRequest.toBasicString()}");
|
|
var attribute_values = updateItemRequest.ExpressionAttributeValues;
|
|
NullReferenceCheckHelper.throwIfNull(attribute_values, () => $"attribute_values is null !!! - {updateItemRequest.toBasicString()}");
|
|
|
|
result = tryFillupTimestamps( ref statement
|
|
, attribute_names, attribute_values
|
|
, DateTimeHelper.Current
|
|
, isUpsert );
|
|
if(result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
updateItemRequest.UpdateExpression = statement;
|
|
|
|
return result;
|
|
}
|
|
|
|
private static Result tryFillupTimestamps( ref string statement
|
|
, Dictionary<string, string> attributeNames, Dictionary<string, AttributeValue> attributeValues
|
|
, DateTime currentTime
|
|
, bool isUpsert = false )
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
result = fillupStatementForTimestamps(ref statement, isUpsert);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
fillupAttributeNameForTimestamps(attributeNames, isUpsert);
|
|
fillupAttributeValueWithTimestamps(attributeValues, currentTime, isUpsert);
|
|
|
|
return result;
|
|
}
|
|
|
|
private static Result tryFillupTimestamps( ref string statement
|
|
, Dictionary<string, string> attributeNames, Dictionary<string, DynamoDBEntry> attributeValues
|
|
, DateTime currentTime
|
|
, bool isUpsert = false )
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
result = fillupStatementForTimestamps(ref statement, isUpsert);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
fillupAttributeNameForTimestamps(attributeNames, isUpsert);
|
|
fillupDynamoDBEntryWithTimestamps(attributeValues, currentTime, isUpsert);
|
|
|
|
return result;
|
|
}
|
|
|
|
private static Result fillupStatementForTimestamps(ref string statement, bool isUpsert = false)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
if (statement.isNullOrWhiteSpace())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
if (false == statement.Contains("SET"))
|
|
{
|
|
err_msg = $"Not found SET keyword in ExpressionStatement !!!";
|
|
result.setFail(ServerErrorCode.DynamoDbExpressionError, err_msg);
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return result;
|
|
}
|
|
|
|
// Expression 설정: UpdatedTime을 설정하고, 항상 UpdatedTime 갱신 한다.
|
|
if (false == statement.Contains($"#{DynamoDbDocBase.UpdatedDateTime}"))
|
|
{
|
|
if (true == statement.Contains("#") || true == statement.Contains(":"))
|
|
{
|
|
statement += ",";
|
|
}
|
|
|
|
statement += $" #{DynamoDbDocBase.UpdatedDateTime} = :{DynamoDbDocBase.UpdatedDateTime}";
|
|
}
|
|
|
|
if (true == isUpsert)
|
|
{
|
|
// Expression 설정: 아이템이 없을 때 CreatedTime을 설정하고, 항상 UpdatedTime 갱신 한다.
|
|
if (false == statement.Contains($"#{DynamoDbDocBase.CreatedDateTime}"))
|
|
{
|
|
statement += $", #{DynamoDbDocBase.CreatedDateTime} = if_not_exists(#{DynamoDbDocBase.CreatedDateTime}, :{DynamoDbDocBase.CreatedDateTime})";
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static void fillupAttributeValueWithTimestampsForInsert( Dictionary<string, AttributeValue> attributeValues, DateTime currentTime )
|
|
{
|
|
// 현재 시간 설정
|
|
var current_time = currentTime.toStringWithUtcIso8601();
|
|
|
|
attributeValues[DynamoDbDocBase.CreatedDateTime] = new AttributeValue { S = current_time };
|
|
attributeValues[DynamoDbDocBase.UpdatedDateTime] = new AttributeValue { S = current_time };
|
|
}
|
|
|
|
private static void fillupAttributeNameForTimestamps( Dictionary<string, string> attributeNames
|
|
, bool isUpsert = false )
|
|
{
|
|
attributeNames[$"#{DynamoDbDocBase.UpdatedDateTime}"] = $"{DynamoDbDocBase.UpdatedDateTime}";
|
|
|
|
if (true == isUpsert)
|
|
{
|
|
attributeNames[$"#{DynamoDbDocBase.CreatedDateTime}"] = $"{DynamoDbDocBase.CreatedDateTime}";
|
|
}
|
|
}
|
|
|
|
private static void fillupAttributeValueWithTimestamps( Dictionary<string, AttributeValue> attributeValues
|
|
, DateTime currentTime
|
|
, bool isUpsert = false )
|
|
{
|
|
// 현재 시간 설정
|
|
var current_time = currentTime.toStringWithUtcIso8601();
|
|
|
|
attributeValues[$":{DynamoDbDocBase.UpdatedDateTime}"] = new AttributeValue { S = current_time };
|
|
|
|
if (true == isUpsert)
|
|
{
|
|
attributeValues[$":{DynamoDbDocBase.CreatedDateTime}"] = new AttributeValue { S = current_time };
|
|
}
|
|
}
|
|
|
|
private static void fillupDynamoDBEntryWithTimestamps( Dictionary<string, DynamoDBEntry> attributeValues
|
|
, DateTime currentTime
|
|
, bool isUpsert = false )
|
|
{
|
|
attributeValues[$":{DynamoDbDocBase.CreatedDateTime}"] = currentTime;
|
|
|
|
if (true == isUpsert)
|
|
{
|
|
attributeValues[$":{DynamoDbDocBase.CreatedDateTime}"] = currentTime;
|
|
}
|
|
}
|
|
|
|
public static async Task<(Result, bool)> checkIfDocumentExists( this DynamoDbClient dbClient
|
|
, DYNAMO_DB_TABLE_NAME tableName
|
|
, Document toCheckDocument
|
|
, bool isConsistentRead = false)
|
|
{
|
|
ArgumentNullReferenceCheckHelper.throwIfNull(toCheckDocument, () => $"toCheckDocument is null !!!");
|
|
|
|
var db_connector = dbClient.getDbClient();
|
|
NullReferenceCheckHelper.throwIfNull(db_connector, () => $"db_connector is null !!! - {toCheckDocument.toBasicString()}, tableName:{tableName}");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var projection_field = DynamoDbDocBase.CreatedDateTime;
|
|
|
|
(result, var primary_key) = toCheckDocument.toPrimaryKey();
|
|
if(result.isFail())
|
|
{
|
|
return (result, false);
|
|
}
|
|
NullReferenceCheckHelper.throwIfNull(primary_key, () => $"primary_key is null !!! - {toCheckDocument.toBasicString()}, tableName:{tableName}");
|
|
|
|
// GetItemRequest 설정
|
|
var get_request = new GetItemRequest
|
|
{
|
|
TableName = tableName,
|
|
Key = primary_key.toKeyWithAttributeValue(),
|
|
ProjectionExpression = projection_field,
|
|
ConsistentRead = isConsistentRead // 일관된 읽기를 사용하지 않음 (성능 최적화)
|
|
};
|
|
|
|
try
|
|
{
|
|
var response = await db_connector.GetItemAsync(get_request);
|
|
if(false == response.IsItemSet)
|
|
{
|
|
err_msg = $"Not found PrimaryKey in DynamoDb !!! - DbTable:{tableName}, {primary_key.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
|
|
return (result, false);
|
|
}
|
|
|
|
if (true == response.Item.TryGetValue(projection_field, out var found_date_time))
|
|
{
|
|
toCheckDocument[projection_field] = found_date_time.S;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
err_msg = $"Exception !!!, Failed to perform in checkIfPrimaryKeyExists() !!! : exception:{e} - {primary_key.toBasicString()}, tableName:{tableName}";
|
|
result.setFail(ServerErrorCode.DynamoDbException, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, false);
|
|
}
|
|
|
|
return (result, true);
|
|
}
|
|
|
|
public static DynamoDbDocumentQueryContext createDocumentQueryContext( this Amazon.DynamoDBv2.DocumentModel.Document document
|
|
, DYNAMO_DB_TABLE_FULL_NAME tableFullName
|
|
, QueryType queryType
|
|
, DynamoDbQueryExceptionNotifier.ExceptionHandler? exceptionHandler = null )
|
|
{
|
|
return new DynamoDbDocumentQueryContext(tableFullName, document, queryType, exceptionHandler);
|
|
}
|
|
|
|
public static Result tryFillupTimestamps(this Amazon.DynamoDBv2.DocumentModel.Document document, QueryType queryType)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var currenct_time = DateTimeHelper.Current;
|
|
|
|
if (QueryType.Insert == queryType)
|
|
{
|
|
document[DynamoDbDocBase.CreatedDateTime] = currenct_time;
|
|
document[DynamoDbDocBase.UpdatedDateTime] = currenct_time;
|
|
}
|
|
else if(QueryType.Update == queryType)
|
|
{
|
|
document[DynamoDbDocBase.UpdatedDateTime] = currenct_time;
|
|
}
|
|
else
|
|
{
|
|
err_msg = $"Invalid DynamoDbDocumentQueryContext.QueryType !!! : queryType:{queryType} - {document.toPKSK()}";
|
|
result.setFail(ServerErrorCode.DynamoDbDocumentQueryContextTypeInvalid, err_msg);
|
|
|
|
return result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static string getPK(this Amazon.DynamoDBv2.DocumentModel.Document document)
|
|
{
|
|
var doc_type = "Empty !!!";
|
|
|
|
if (false == document.TryGetValue(PrimaryKey.PK_Define, out var db_entry))
|
|
{
|
|
Log.getLogger().fatal($"Not found PrimaryKey.PK_Define !!! : {document.toBasicString()}");
|
|
|
|
return doc_type;
|
|
}
|
|
return db_entry.AsString();
|
|
}
|
|
|
|
public static string getSK(this Amazon.DynamoDBv2.DocumentModel.Document document)
|
|
{
|
|
var doc_type = "Empty !!!";
|
|
|
|
if (false == document.TryGetValue(PrimaryKey.SK_Define, out var db_entry))
|
|
{
|
|
Log.getLogger().fatal($"Not found PrimaryKey.SK_Define !!! : {document.toBasicString()}");
|
|
|
|
return doc_type;
|
|
}
|
|
return db_entry.AsString();
|
|
}
|
|
|
|
public static string toPKSK(this Amazon.DynamoDBv2.DocumentModel.Document document)
|
|
{
|
|
return $"PK:{document.getPK()}, SK:{document.getSK()}";
|
|
}
|
|
|
|
public static string getDocType(this Amazon.DynamoDBv2.DocumentModel.Document document)
|
|
{
|
|
var doc_type = "Empty !!!";
|
|
|
|
if(false == document.TryGetValue("DocType", out var db_entry))
|
|
{
|
|
Log.getLogger().fatal($"Not found DocType !!! : {document.toBasicString()}");
|
|
|
|
return doc_type;
|
|
}
|
|
return db_entry.AsString(); }
|
|
|
|
public static bool isValid(this Amazon.DynamoDBv2.DocumentModel.Document document)
|
|
{
|
|
if (document.getPK() == string.Empty || document.getSK() == string.Empty || document.getDocType() == string.Empty)
|
|
{
|
|
Log.getLogger().error($"PK or SK or DocType is empty !!! : {document.toBasicString()}");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static bool fillupAttribObject<TAttrib>(this Amazon.DynamoDBv2.DocumentModel.Document document, out TAttrib? fillupAttrib)
|
|
where TAttrib : AttribBase, new()
|
|
{
|
|
fillupAttrib = null;
|
|
var attrib_type_name = typeof(TAttrib).Name;
|
|
|
|
try
|
|
{
|
|
var dynamo_db_entry = document.findAttribObjectWithCaseInsensitive<TAttrib>();
|
|
if (null == dynamo_db_entry)
|
|
{
|
|
Log.getLogger().fatal($"Failed to findAttribObjectWithCaseInsensitive() !!!, Not found AttribType in Document of DynamoDbTable !!! - AttribType:{attrib_type_name}");
|
|
return false;
|
|
}
|
|
|
|
TAttrib? attrib_object = null;
|
|
|
|
if (dynamo_db_entry.isJsonEncoded())
|
|
{
|
|
attrib_object = JsonConvert.DeserializeObject<TAttrib>(dynamo_db_entry.AsString());
|
|
if (null == attrib_object)
|
|
{
|
|
Log.getLogger().fatal($"Failed to JsonConvert.DeserializeObject<TAttrib> in DynamoDBEntry of DynamoDbTable !!! - AttribType:{attrib_type_name}");
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
attrib_object = DynamoDbClientHelper.dynamoDbDocumentToClass<TAttrib>(dynamo_db_entry);
|
|
if (null == attrib_object)
|
|
{
|
|
Log.getLogger().fatal($"Failed to DynamoDbClientHelper.dynamoDbDocumentToClass<TAttrib> in DynamoDBEntry of DynamoDbTable !!! - AttribType:{attrib_type_name}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
fillupAttrib = attrib_object;
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error_code = ServerErrorCode.TryCatchException;
|
|
Log.getLogger().fatal($"Exception !!!, Failed to get AttribBase in DynamoDBEntry of DynamoDbTable !!! : errorCode:{error_code}, exception:{e} - AttribType:{attrib_type_name}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static Amazon.DynamoDBv2.DocumentModel.DynamoDBEntry? findAttribObjectWithCaseInsensitive<TAttrib>(this Amazon.DynamoDBv2.DocumentModel.Document document)
|
|
where TAttrib : AttribBase
|
|
{
|
|
var attrib_type_name = typeof(TAttrib).Name;
|
|
|
|
var attribute_map = document.ToAttributeMap();
|
|
foreach(var each in attribute_map)
|
|
{
|
|
if(true == each.Key.Equals(attrib_type_name, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return document[each.Key];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public static bool setAttribObject<TAttrib>(this Amazon.DynamoDBv2.DocumentModel.Document document, TAttrib fillupAttrib)
|
|
where TAttrib : AttribBase
|
|
{
|
|
var attrib_type_name = typeof(TAttrib).Name;
|
|
|
|
var is_save_to_json_in_db = fillupAttrib.isSaveToJsonInDb();
|
|
|
|
try
|
|
{
|
|
var dynamo_db_entry = document.findAttribObjectWithCaseInsensitive<TAttrib>();
|
|
if (null == dynamo_db_entry)
|
|
{
|
|
if(true == is_save_to_json_in_db)
|
|
{
|
|
document[attrib_type_name] = fillupAttrib.toJsonString();
|
|
}
|
|
else
|
|
{
|
|
document[attrib_type_name] = fillupAttrib.toDocument();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (true == is_save_to_json_in_db)
|
|
{
|
|
dynamo_db_entry = fillupAttrib.toJsonString();
|
|
}
|
|
else
|
|
{
|
|
dynamo_db_entry = fillupAttrib.toDocument();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error_code = ServerErrorCode.TryCatchException;
|
|
Log.getLogger().fatal($"Exception !!!, Failed to set AttribBase in DynamoDBEntry of DynamoDbTable !!! : errorCode:{error_code}, exception:{e} - AttribType:{attrib_type_name}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static bool getTimestampByDB_TIMESTAMP(this Amazon.DynamoDBv2.DocumentModel.Document document, DB_TIMESTAMP timestampName, out DateTime createdDateTime)
|
|
{
|
|
createdDateTime = DateTime.MinValue;
|
|
try
|
|
{
|
|
if(false == document.TryGetValue(timestampName, out var datetime))
|
|
{
|
|
return false;
|
|
}
|
|
createdDateTime = datetime.AsString().toUtcTime();
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error_code = ServerErrorCode.TryCatchException;
|
|
Log.getLogger().fatal($"Exception !!!, Failed to get document[{timestampName}] in DynamoDbTable !!! : errorCode:{error_code}, exception:{e} - {document.toBasicString()}");
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static async Task<(Result, TDoc?)> simpleQueryDocTypeWithQueryOperationConfig<TDoc>( this DynamoDbClient dbClient
|
|
, QueryOperationConfig queryOperationConfig
|
|
, bool isFailOnEmptyDoc = true
|
|
, string eventTid = "" )
|
|
where TDoc : DynamoDbDocBase, new()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var to_copy_doc = new TDoc();
|
|
var table = dbClient.getTableByName(to_copy_doc.TableName);
|
|
|
|
var search = table.queryWithStopwatch(queryOperationConfig, eventTid);
|
|
if (search == null)
|
|
{
|
|
err_msg = $"Failed to Table.Query !!! : Doc:{typeof(TDoc).Name} - {table.toBasicString()}";
|
|
result.setFail(ServerErrorCode.DynamoDbQueryFailed, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return (result, null);
|
|
}
|
|
|
|
var next_documents = await search.GetNextSetAsync();
|
|
if ( null == next_documents
|
|
|| 0 >= next_documents.Count)
|
|
{
|
|
if(true == isFailOnEmptyDoc)
|
|
{
|
|
err_msg = $"No match Doc !!! : Doc:{typeof(TDoc).Name} - {table.toBasicString()}";
|
|
result.setFail(ServerErrorCode.DynamoDbQueryNoMatchAttribute, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
}
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
var source_document = next_documents[0];
|
|
|
|
result = await to_copy_doc.onCopyFromDocument(source_document);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to onCopyFromDocument() !!! : {result.toBasicString()}, TgtDoc:{typeof(TDoc).Name} <= SrcDoc:{source_document.toBasicString()} - {table.toBasicString()}";
|
|
result.setFail(ServerErrorCode.DynamoDbDocumentCopyFailedToDoc, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, to_copy_doc);
|
|
}
|
|
|
|
public static async Task<(Result, List<TDoc>)> simpleQueryDocTypesWithQueryOperationConfig<TDoc>( this DynamoDbClient dbClient
|
|
, QueryOperationConfig queryOperationConfig
|
|
, bool isFailOnEmptyDoc = false
|
|
, string eventTid = "" )
|
|
where TDoc : DynamoDbDocBase, new()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var table = dbClient.getTableByDoc<TDoc>();
|
|
|
|
var doc_bases = new List<TDoc>();
|
|
|
|
var search = table.queryWithStopwatch(queryOperationConfig, eventTid);
|
|
while (search.IsDone == false)
|
|
{
|
|
var next_documents = await search.GetNextSetAsync();
|
|
if(null == next_documents)
|
|
{
|
|
break;
|
|
}
|
|
|
|
foreach (var document in next_documents)
|
|
{
|
|
var doc = new TDoc();
|
|
|
|
result = await doc.onCopyFromDocument(document);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to onCopyFromDocument() !!! : {result.toBasicString()}, TgtDoc:{typeof(TDoc).Name} <= SrcDoc:{document.toBasicString()} - {table.toBasicString()}";
|
|
result.setFail(ServerErrorCode.DynamoDbDocumentCopyFailedToDoc, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, doc_bases);
|
|
}
|
|
doc_bases.Add(doc);
|
|
}
|
|
}
|
|
|
|
if( 0 >= doc_bases.Count
|
|
&& true == isFailOnEmptyDoc)
|
|
{
|
|
err_msg = $"No match Doc !!! : Doc:{typeof(TDoc).Name} - {table.toBasicString()}";
|
|
result.setFail(ServerErrorCode.DynamoDbQueryNoMatchAttribute, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
}
|
|
|
|
return (result, doc_bases);
|
|
}
|
|
|
|
public static async Task<(Result, TDoc?)> simpleQueryDocTypeWithScanOperationConfig<TDoc>( this DynamoDbClient dbClient
|
|
, ScanOperationConfig scanOperationConfig)
|
|
where TDoc : DynamoDbDocBase, new()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var table = dbClient.getTableByDoc<TDoc>();
|
|
|
|
var search = table.Scan(scanOperationConfig);
|
|
if (search == null)
|
|
{
|
|
err_msg = $"Failed to Table.Query !!! : Doc:{typeof(TDoc).Name} - {table.toBasicString()}";
|
|
result.setFail(ServerErrorCode.DynamoDbQueryFailed, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return (result, null);
|
|
}
|
|
|
|
var next_documents = await search.GetNextSetAsync();
|
|
if ( null == next_documents
|
|
|| 0 >= next_documents.Count)
|
|
{
|
|
err_msg = $"No match Doc !!! : Doc:{typeof(TDoc).Name} - {table.TableName}";
|
|
result.setFail(ServerErrorCode.DynamoDbQueryNoMatchAttribute, err_msg);
|
|
Log.getLogger().warn(result.toBasicString());
|
|
return (result, null);
|
|
}
|
|
|
|
var source_document = next_documents[0];
|
|
|
|
var to_copy_doc = new TDoc();
|
|
result = await to_copy_doc.onCopyFromDocument(source_document);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to onCopyFromDocument !!! : {result.toBasicString()}, TgtDoc:{typeof(TDoc).Name} <= SrcDoc:{source_document.toBasicString()} - {table.toBasicString()}";
|
|
result.setFail(ServerErrorCode.DynamoDbDocumentCopyFailedToDoc, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, to_copy_doc);
|
|
}
|
|
|
|
public static async Task<(Result, List<TDoc>)> simpleQueryDocTypesWithScanOperationConfig<TDoc>( this DynamoDbClient dbClient
|
|
, ScanOperationConfig scanOperationConfig
|
|
, bool isFailOnCriticalError = false )
|
|
where TDoc : DynamoDbDocBase, new()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var table = dbClient.getTableByDoc<TDoc>();
|
|
|
|
var doc_bases = new List<TDoc>();
|
|
|
|
var search = table.Scan(scanOperationConfig);
|
|
while (search.IsDone == false)
|
|
{
|
|
var next_documents = await search.GetNextSetAsync();
|
|
if(null == next_documents)
|
|
{
|
|
return (result, doc_bases);
|
|
}
|
|
|
|
foreach (var document in next_documents)
|
|
{
|
|
var doc = new TDoc();
|
|
|
|
result = await doc.onCopyFromDocument(document);
|
|
if (result.isFail())
|
|
{
|
|
if (true == isFailOnCriticalError)
|
|
{
|
|
err_msg = $"Failed to onCopyFromDocument() !!!, by Critical Error !!! : {result.toBasicString()}, TgtDoc:{typeof(TDoc).Name} <= SrcDoc:{document.toBasicString()} - {table.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return (result, doc_bases);
|
|
}
|
|
else
|
|
{
|
|
err_msg = $"Failed to onCopyFromDocument() !!! : {result.toBasicString()}, TgtDoc:{typeof(TDoc).Name} <= SrcDoc:{document.toBasicString()} - {table.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
}
|
|
continue;
|
|
}
|
|
doc_bases.Add(doc);
|
|
}
|
|
}
|
|
|
|
return (result, doc_bases);
|
|
}
|
|
|
|
public static async Task<(Result, TDoc?)> simpleQueryTransactReadDocWithItemRequest<TDoc>( this DynamoDbClient dbClient
|
|
, TransactGetItem toReadTransactQuery
|
|
, bool isFailOnEmptyData = false
|
|
, UInt16 retryCount = 3 )
|
|
where TDoc : DynamoDbDocBase, new()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var get_items = new List<TransactGetItem>() { toReadTransactQuery };
|
|
(result, var read_documents) = await dbClient.simpleTransactReadOfItemRequestWithItemRequest(get_items, isFailOnEmptyData, retryCount);
|
|
if(result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
|
|
foreach (var each in read_documents)
|
|
{
|
|
var table_name = each.Key;
|
|
var documents = each.Value;
|
|
|
|
foreach (var document in documents)
|
|
{
|
|
var doc = new TDoc();
|
|
|
|
result = await doc.onCopyFromDocument(document);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to onCopyFromDocument() !!! : {result.toBasicString()}, TgtDoc:{typeof(TDoc).Name} <= SrcDoc:{document.toBasicString()} - {table_name}";
|
|
result.setFail(ServerErrorCode.DynamoDbDocumentCopyFailedToDoc, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, doc);
|
|
}
|
|
}
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
|
|
public static async Task<(Result, Dictionary<DYNAMO_DB_TABLE_NAME, List<TDoc>>)> simpleQueryTransactReadDocsWithItemRequest<TDoc>( this DynamoDbClient dbClient
|
|
, List<TransactGetItem> toReadTransactQueries
|
|
, bool isFailOnEmptyData = false
|
|
, UInt16 retryCount = 3 )
|
|
where TDoc : DynamoDbDocBase, new()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var doc_bases = new Dictionary<DYNAMO_DB_TABLE_NAME, List<TDoc>>();
|
|
|
|
(result, var read_documents) = await dbClient.simpleTransactReadOfItemRequestWithItemRequest(toReadTransactQueries, isFailOnEmptyData, retryCount);
|
|
if(result.isFail())
|
|
{
|
|
return (result, doc_bases);
|
|
}
|
|
|
|
foreach (var each in read_documents)
|
|
{
|
|
var table_name = each.Key;
|
|
var documents = each.Value;
|
|
|
|
if (false == read_documents.TryGetValue(table_name, out var has_documents))
|
|
{
|
|
has_documents = new List<Document>();
|
|
read_documents.Add(table_name, has_documents);
|
|
}
|
|
|
|
foreach (var document in documents)
|
|
{
|
|
var doc = new TDoc();
|
|
|
|
result = await doc.onCopyFromDocument(document);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to onCopyFromDocument() !!! : {result.toBasicString()}, TgtDoc:{typeof(TDoc).Name} <= SrcDoc:{document.toBasicString()} - {table_name}";
|
|
result.setFail(ServerErrorCode.DynamoDbDocumentCopyFailedToDoc, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return (result, doc_bases);
|
|
}
|
|
has_documents.Add(document);
|
|
}
|
|
}
|
|
|
|
return (result, doc_bases);
|
|
}
|
|
|
|
public static async Task<Result> simpleInsertDocumentWithDocType<TDoc>( this DynamoDbClient dynamoDbClient, TDoc docBase
|
|
, string eventTid = "")
|
|
where TDoc : DynamoDbDocBase
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var table = dynamoDbClient.getTableByName(docBase.TableName);
|
|
|
|
if (QueryType.Insert != docBase.getQueryType())
|
|
{
|
|
result = await docBase.newDoc4Query();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to newDoc4Query() !!! : {result.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
(result, var copied_doc) = await docBase.onCopyToDocument();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to onCopyToDocument() !!! : {result.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
result = await table.simpleInsertDocument(copied_doc, eventTid);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to simpleInsertDocument() !!! : {result.toBasicString()}, {copied_doc.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}";
|
|
Log.getLogger().error(result.toBasicString());
|
|
return result;
|
|
}
|
|
|
|
Log.getLogger().debug($"Db insert from simpleInsertDocument() !!! : {copied_doc.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}");
|
|
|
|
return result;
|
|
}
|
|
|
|
public static async Task<Result> simpleUpsertDocumentWithDocType<TDoc>( this DynamoDbClient dynamoDbClient, TDoc docBase
|
|
, string eventTid = "")
|
|
where TDoc : DynamoDbDocBase
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var table = dynamoDbClient.getTableByName(docBase.TableName);
|
|
|
|
if (QueryType.Upsert != docBase.getQueryType())
|
|
{
|
|
result = await docBase.upsertDoc4Query();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to upsertDoc4Query() !!! : {result.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
(result, var copied_doc) = await docBase.onCopyToDocument();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to onCopyToDocument() !!! : {result.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
result = await copied_doc.tryFillupTimestampsForUpsert(dynamoDbClient, table.TableName);
|
|
if(result.isFail())
|
|
{
|
|
err_msg = $"Failed to tryFillupTimestampsForUpsert() !!! : {result.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
(result, _) = await table.simpleUpsertDocument(copied_doc, eventTid);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to simpleUpsertDocument() !!! : {result.toBasicString()}, {copied_doc.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}";
|
|
Log.getLogger().error(result.toBasicString());
|
|
return result;
|
|
}
|
|
|
|
Log.getLogger().debug($"Db upsert from simpleUpsertDocument() !!! : {copied_doc.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}");
|
|
|
|
return result;
|
|
}
|
|
|
|
public static async Task<Result> simpleUpdateDocumentWithDocType<TDoc>( this DynamoDbClient dynamoDbClient, TDoc docBase
|
|
, string eventTid = "" )
|
|
where TDoc : DynamoDbDocBase
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var table = dynamoDbClient.getTableByName(docBase.TableName);
|
|
|
|
if (QueryType.Update != docBase.getQueryType())
|
|
{
|
|
result = await docBase.updateDoc4Query();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to updateDoc4Query() !!! : {result.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
(result, var copied_doc) = await docBase.onCopyToDocument();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to onCopyToDocument() !!! : {result.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
(result, _) = await table.simpleUpdateDocument(copied_doc, eventTid);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to simpleUpdateDocument() !!! : {result.toBasicString()}, {copied_doc.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
Log.getLogger().debug($"Db update from simpleUpdateDocument() !!! : {copied_doc.toBasicString()} - {typeof(TDoc).Name}, {table.toBasicString()}");
|
|
|
|
return result;
|
|
}
|
|
|
|
public static async Task<Result> simpleDeleteDocumentWithDocType<TDoc>( this DynamoDbClient dynamoDbClient, TDoc docBase
|
|
, string eventTid = "" )
|
|
where TDoc : DynamoDbDocBase
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var table = dynamoDbClient.getTableByName(docBase.TableName);
|
|
|
|
if (QueryType.Delete != docBase.getQueryType())
|
|
{
|
|
result = await docBase.deleteDoc4Query();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to deleteDoc4Query() !!! : {result.toBasicString()} - {typeof(TDoc).Name}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
(result, var copied_doc) = await docBase.onCopyToDocument();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to onCopyToDocument() !!! : {result.toBasicString()} - {typeof(TDoc).Name}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
result = await table.simpleDeleteDocument(copied_doc, eventTid);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to simpleDeleteDocument() !!! : {result.toBasicString()}, {copied_doc.toBasicString()} - {typeof(TDoc).Name}";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
Log.getLogger().debug($"Db delete from simpleDeleteDocument() !!! : {copied_doc.toBasicString()} - {typeof(TDoc).Name}");
|
|
|
|
return result;
|
|
}
|
|
|
|
public static async Task<(Result, DynamoDbDocumentQueryContext?)> toDocumentQueryContext<TDoc>( this TDoc dbBaseDoc )
|
|
where TDoc : DynamoDbDocBase
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = ServerLogicApp.getServerLogicApp();
|
|
var dynamo_db_connector = server_logic.getDynamoDbClient();
|
|
|
|
(result, var copied_doc) = await dbBaseDoc.onCopyToDocument();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to onCopyToDocument() from TDoc !!! : {result.toBasicString()} - {typeof(TDoc).Name}";
|
|
Log.getLogger().error(err_msg);
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, new DynamoDbDocumentQueryContext(dynamo_db_connector.getTableFullName(dbBaseDoc.TableName), copied_doc, dbBaseDoc.getQueryType(), dbBaseDoc.getExceptionHandler()));
|
|
}
|
|
|
|
public static async Task<(Result, TAttrib?)> simpleQueryDocTypeToAttrib<TDoc, TAttrib>( this DynamoDbClient dynamoDbClient
|
|
, string pk, string sk = DynamoDbClient.SK_EMPTY
|
|
, string eventTid = "")
|
|
where TDoc : DynamoDbDocBase, new()
|
|
where TAttrib : AttribBase
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
(result, var make_primary_key) = await makePrimaryKey<TDoc>(pk, sk);
|
|
if (result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!!");
|
|
var query_config = dynamoDbClient.makeQueryConfigForReadByPKSK(make_primary_key.PK, make_primary_key.SK);
|
|
|
|
(result, var found_base_doc) = await dynamoDbClient.simpleQueryDocTypeWithQueryOperationConfig<TDoc>(query_config, eventTid:eventTid);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to simpleQueryDocTypeWithQueryOperationConfig() !!! : {result.toBasicString()}, {make_primary_key.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return (result, null);
|
|
}
|
|
NullReferenceCheckHelper.throwIfNull(found_base_doc, () => $"found_base_doc is null !!! - {make_primary_key.toBasicString()}");
|
|
|
|
var found_attrib = found_base_doc.getAttrib<TAttrib>();
|
|
NullReferenceCheckHelper.throwIfNull(found_attrib, () => $"found_attrib is null !!! - {make_primary_key.toBasicString()}");
|
|
|
|
return (result, found_attrib);
|
|
}
|
|
|
|
public static async Task<(Result, List<TAttrib>?)> simpleQueryDocTypesToAttrib<TDoc, TAttrib>( this DynamoDbClient dynamoDbClient
|
|
, string pk, string sk = DynamoDbClient.SK_EMPTY
|
|
, string eventTid = "")
|
|
where TDoc : DynamoDbDocBase, new()
|
|
where TAttrib : AttribBase
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
(result, var make_primary_key) = await makePrimaryKey<TDoc>(pk, sk);
|
|
if (result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!!");
|
|
var query_config = dynamoDbClient.makeQueryConfigForReadByPKSK(make_primary_key.PK, make_primary_key.SK);
|
|
|
|
(result, var found_base_doc_list) = await dynamoDbClient.simpleQueryDocTypesWithQueryOperationConfig<TDoc>(query_config, eventTid:eventTid);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to simpleQueryDocTypesWithQueryOperationConfig() !!! : {result.toBasicString()}, {make_primary_key.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return (result, null);
|
|
}
|
|
|
|
var found_attrib_list = new List<TAttrib>();
|
|
|
|
foreach(var found_base_doc in found_base_doc_list)
|
|
{
|
|
var found_attrib = found_base_doc.getAttrib<TAttrib>();
|
|
NullReferenceCheckHelper.throwIfNull(found_attrib, () => $"found_attrib is null !!! - {make_primary_key.toBasicString()}");
|
|
|
|
found_attrib_list.Add(found_attrib);
|
|
}
|
|
|
|
return (result, found_attrib_list);
|
|
}
|
|
|
|
public static (Result, PrimaryKey?) toPrimaryKey(this Amazon.DynamoDBv2.DocumentModel.Document document)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
if(false == document.TryGetValue(PrimaryKey.PK_Define, out var found_pk))
|
|
{
|
|
err_msg = $"Not found PK in Document !!! : {document.toBasicString()}";
|
|
result.setFail(ServerErrorCode.DynamoDbPrimaryKeyNotFound, err_msg);
|
|
|
|
return (result, null);
|
|
}
|
|
var pk = found_pk.AsString();
|
|
|
|
if (false == document.TryGetValue(PrimaryKey.SK_Define, out var found_sk))
|
|
{
|
|
err_msg = $"Not found SK in Document !!! : {document.toBasicString()}";
|
|
|
|
result.setFail(ServerErrorCode.DynamoDbPrimaryKeyNotFound, err_msg);
|
|
return (result, null);
|
|
}
|
|
var sk = found_sk.AsString();
|
|
|
|
return (result, new PrimaryKey(pk, sk));
|
|
}
|
|
|
|
public static async Task<(Result, TDoc?)> simpleQueryDocTypesWithUpdateItemRequest<TDoc>( this DynamoDbClient dbClient
|
|
, UpdateItemRequest updateItemRequest
|
|
, string eventTid = "")
|
|
where TDoc : DynamoDbDocBase, new()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
(result, var updated_doc) = await dbClient.simpleQueryWithUpdateItemRequest(updateItemRequest, false, eventTid);
|
|
if(result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
NullReferenceCheckHelper.throwIfNull(updated_doc, () => $"updated_doc is null !!!");
|
|
|
|
var doc = new TDoc();
|
|
|
|
result = await doc.onCopyFromDocument(updated_doc);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to onCopyFromDocument() !!! : {result.toBasicString()}, TgtDoc:{typeof(TDoc).Name} <= SrcDoc:{updated_doc.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, doc);
|
|
}
|
|
|
|
public static async Task<Result> createIfNotExist<TDoc>( this DynamoDbClient dbClient
|
|
, TDoc toInsertDoc, Action<TDoc> initFunc)
|
|
where TDoc : DynamoDbDocBase, new()
|
|
{
|
|
var result = new Result();
|
|
|
|
var make_primary_key = toInsertDoc.getPrimaryKey();
|
|
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!!");
|
|
|
|
(result, var is_exist) = await dbClient.checkIfAttributeExists(dbClient.getTableFullName(toInsertDoc.TableName), make_primary_key);
|
|
if(result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
if(false == is_exist)
|
|
{
|
|
if(null != initFunc)
|
|
{
|
|
initFunc(toInsertDoc);
|
|
}
|
|
|
|
return await dbClient.simpleInsertDocumentWithDocType<TDoc>(toInsertDoc);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static async Task<(Result, bool)> checkIfAttributeExists( this DynamoDbClient dbClient
|
|
, DYNAMO_DB_TABLE_FULL_NAME tableFullName
|
|
, PrimaryKey targetPrimaryKey
|
|
, bool isConsistentRead = false)
|
|
{
|
|
var db_connector = dbClient.getDbClient();
|
|
NullReferenceCheckHelper.throwIfNull(db_connector, () => $"db_connector is null !!! - {targetPrimaryKey.toBasicString()}");
|
|
ConditionValidCheckHelper.throwIfFalseWithCondition(() => false == tableFullName.isNullOrWhiteSpace(), () => $"Invalid TableFullName !!! - {targetPrimaryKey.toBasicString()}");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var projection_field = DynamoDbDocBase.CreatedDateTime;
|
|
|
|
// GetItemRequest 설정
|
|
var get_request = new GetItemRequest
|
|
{
|
|
TableName = tableFullName,
|
|
Key = targetPrimaryKey.toKeyWithAttributeValue(),
|
|
ProjectionExpression = projection_field,
|
|
ConsistentRead = isConsistentRead // 일관된 읽기를 사용하지 않음 (성능 최적화)
|
|
};
|
|
|
|
try
|
|
{
|
|
var response = await db_connector.GetItemAsync(get_request);
|
|
if(false == response.IsItemSet)
|
|
{
|
|
err_msg = $"Not found PrimaryKey in DynamoDb !!! : {get_request.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
|
|
return (result, false);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error_code = ServerErrorCode.DynamoDbException;
|
|
err_msg = $"Exception !!!, Failed to perform in checkIfPrimaryKeyExists() !!! : errorCode:{error_code}, exception:{e}, {get_request.toBasicString()}";
|
|
result.setFail(error_code, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, false);
|
|
}
|
|
|
|
return (result, true);
|
|
}
|
|
|
|
public static bool setAttribObjectWithJsonString<TAttrib>(this JObject jobject, TAttrib fillupAttrib)
|
|
where TAttrib : AttribBase
|
|
{
|
|
var attrib_type_name = typeof(TAttrib).Name;
|
|
|
|
try
|
|
{
|
|
jobject[attrib_type_name] = JObject.Parse(fillupAttrib.toJsonString());
|
|
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var error_code = ServerErrorCode.TryCatchException;
|
|
Log.getLogger().fatal($"Exception !!!, Failed to perform in setAttribObjectWithJsonString<{attrib_type_name}>() !!! : errorCode:{error_code}, exception:{e} - AttribType:{attrib_type_name}");
|
|
return false;
|
|
}
|
|
}
|
|
} |