using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Linq.Expressions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.DocumentModel; using Amazon.DynamoDBv2.Model; using ServerCore; using ServerBase; using LINK_PKSK = System.String; namespace ServerBase; /*============================================================================================= DynamoDb 정보 관리 흐름도 # 읽기는 Document Only, 쓰기는 Document + ItemRequest 로 처리는 하는 것이 적절하다 !!! 1. Document Only 시퀀스 * 읽기 => 쓰기 DB => Document => Attrib => Doc => EntityAttribute => Doc => Attrib => Document => DB 2. ItemRequest Only 시퀀스 * 읽기 => 쓰기 DB => ItemRequest => EntityAttribute => ItemRequest => DB 3. Document + ItemRequest 시퀀스 * 읽기 => 쓰기 DB => ItemRequest => Document => Attrib => Doc => Attrib => Document => ItemRequest => DB - kangms //===========================================================================================*/ //============================================================================================= // DynamoDB의 쿼리의 종류를 정의 한다. // // - kangms //============================================================================================= public enum QueryType { None = 0, // 일반 쿼리 Select, // 조회 한다. Insert, // 존재하지 않은 경우만 추가 한다. Update, // 존재하는 경우만 업데이트 한다. Upsert, // 존재하지 않으면 추가하고, 있으면 업데이트 한다. Delete, // 존재하는 경우 삭제 한다. // 특수 쿼리 ExistsDelete, // 존재하지 않을 경우, 삭제되기 전 모든 속성을 반환 한다. } //============================================================================================= // DynamoDB의 PrimaryKey를 설정하는 클래스 이다. // // - kangms //============================================================================================= public class PrimaryKey { public const string PK_Define = "PK"; public const string SK_Define = "SK"; [JsonProperty(PK_Define)] public string PK { get; private set; } = string.Empty; [JsonProperty(SK_Define)] public string SK { get; private set; } = string.Empty; public PrimaryKey() { } public PrimaryKey(string partitionKey) { PK = partitionKey; } public PrimaryKey(string partitionKey, string sortKey) { PK = partitionKey; SK = sortKey; } public bool isFilledPK() { if (true == PK.isNullOrWhiteSpace()) { return false; } return true; } public bool isFilledSK() { if (true == SK.isNullOrWhiteSpace()) { return false; } return true; } public void fillUpPrimaryKey(string partitionKey, string sortKey) { PK = partitionKey; SK = sortKey; } public void fillUpPK(string partitionKey) { PK = partitionKey; } public void fillUpSK(string sortKey) { SK = sortKey; } public void setEmptySK() { SK = DynamoDbClient.SK_EMPTY; } public string toPKSK() { return $"{PK_Define}:{PK}-{SK_Define}:{SK})"; } //===================================================================================== // LINK_PKSK : "PK-SK" //===================================================================================== public static (Result, PrimaryKey?) parseLinkPKSK(LINK_PKSK linkPKSK) { var result = new Result(); var err_msg = string.Empty; var pksk_parts = linkPKSK.Split('-'); if (pksk_parts.Length != 2) { err_msg = $"Invalid length of LinkPKSK !!! : 2 == length:{pksk_parts.Length}"; result.setFail(ServerErrorCode.DynamoDbDocLinkPkSkInvalid, err_msg); Log.getLogger().error(result.toBasicString()); return (result, null); } return (result, new PrimaryKey(pksk_parts[0], pksk_parts[1])); } public string toBasicString() { return $"PrimaryKey({PK_Define}:{PK}, {SK_Define}:{SK})"; } } //============================================================================================= // DynamoDB의 Document Model에서 쿼리할때 옵션을 설정하는 클래스 이다. // // - kangms //============================================================================================= public static class DynamoDbQueryOperationOptionConfig { private static GetItemOperationConfig m_get_item_config = new(); private static TransactWriteItemOperationConfig m_transact_write_config_for_exist_primary_key = new(); private static TransactWriteItemOperationConfig m_transact_write_config_for_not_exist_primary_key = new (); // Select 쿼리후 반환되는 필드 선택 설정 private static TransactGetItemOperationConfig m_transact_get_config = new(); public static void configure() { { m_get_item_config.ConsistentRead = true; } { var expression = new Amazon.DynamoDBv2.DocumentModel.Expression(); expression.ExpressionStatement = $"attribute_exists(#{PrimaryKey.PK_Define}) AND attribute_exists(#{PrimaryKey.SK_Define})"; expression.ExpressionAttributeNames[$"#{PrimaryKey.PK_Define}"] = PrimaryKey.PK_Define; expression.ExpressionAttributeNames[$"#{PrimaryKey.SK_Define}"] = PrimaryKey.SK_Define; m_transact_write_config_for_exist_primary_key.ConditionalExpression = expression; m_transact_write_config_for_exist_primary_key.ReturnValuesOnConditionCheckFailure = Amazon.DynamoDBv2.DocumentModel.ReturnValuesOnConditionCheckFailure.AllOldAttributes; } { var expression = new Amazon.DynamoDBv2.DocumentModel.Expression(); expression.ExpressionStatement = $"attribute_not_exists(#{PrimaryKey.PK_Define}) AND attribute_not_exists(#{PrimaryKey.SK_Define})"; expression.ExpressionAttributeNames[$"#{PrimaryKey.PK_Define}"] = PrimaryKey.PK_Define; expression.ExpressionAttributeNames[$"#{PrimaryKey.SK_Define}"] = PrimaryKey.SK_Define; m_transact_write_config_for_not_exist_primary_key.ConditionalExpression = expression; m_transact_write_config_for_not_exist_primary_key.ReturnValuesOnConditionCheckFailure = Amazon.DynamoDBv2.DocumentModel.ReturnValuesOnConditionCheckFailure.AllOldAttributes; } } public static TransactWriteItemOperationConfig getTransactWriteConfigForExistKey() => m_transact_write_config_for_exist_primary_key; public static TransactWriteItemOperationConfig getTransactWriteConfigForNotExistKey() => m_transact_write_config_for_not_exist_primary_key; public static GetItemOperationConfig getItemConfig() => m_get_item_config; }