static async Task <Dictionary <string, string> > GetAnnotationsAsync( IAmazonDynamoDB client, string tableName, Guid ownerId, Guid scoreId) { var partitionKey = DynamoDbScoreDataUtils.ConvertToPartitionKey(ownerId); var score = ScoreDatabaseUtils.ConvertToBase64(scoreId); var request = new QueryRequest() { TableName = tableName, ExpressionAttributeNames = new Dictionary <string, string>() { ["#owner"] = DynamoDbScoreDataPropertyNames.OwnerId, ["#data"] = DynamoDbScoreDataPropertyNames.DataId, ["#content"] = DynamoDbScoreDataPropertyNames.Content, }, ExpressionAttributeValues = new Dictionary <string, AttributeValue>() { [":owner"] = new AttributeValue(partitionKey), [":annScore"] = new AttributeValue(DynamoDbScoreDataConstant.PrefixAnnotation + score), }, KeyConditionExpression = "#owner = :owner and begins_with(#data, :annScore)", ProjectionExpression = "#data, #content", }; try { var response = await client.QueryAsync(request); var result = new Dictionary <string, string>(); var substringStartIndex = DynamoDbScoreDataConstant.PrefixAnnotation.Length + score.Length; foreach (var item in response.Items) { var hashValue = item[DynamoDbScoreDataPropertyNames.DataId]; var hash = hashValue.S.Substring(substringStartIndex); var contentValue = item[DynamoDbScoreDataPropertyNames.Content]; result[hash] = contentValue.S; } return(result); } catch (Exception ex) { Console.WriteLine(ex.Message); throw; } }
static async Task RemoveDataAsync( IAmazonDynamoDB client, string tableName, Guid ownerId, Guid scoreId, HashSet <string> removeHashSet) { const int chunkSize = 25; var partitionKey = DynamoDbScoreDataUtils.ConvertToPartitionKey(ownerId); var score = ScoreDatabaseUtils.ConvertToBase64(scoreId); var chunkList = removeHashSet.Select((h, index) => (h, index)) .GroupBy(x => x.index / chunkSize) .Select(x => x.Select(x => x.h).ToArray()) .ToArray(); foreach (var hashList in chunkList) { await RemoveData25Async(client, tableName, partitionKey, score, hashList); }
static async Task <(bool success, string description)> TryGetDescriptionAsync( IAmazonDynamoDB client, string tableName, Guid ownerId, Guid scoreId, string descriptionHash) { var partitionKey = DynamoDbScoreDataUtils.ConvertToPartitionKey(ownerId); var score = ScoreDatabaseUtils.ConvertToBase64(scoreId); var request = new GetItemRequest() { TableName = tableName, Key = new Dictionary <string, AttributeValue>() { [DynamoDbScoreDataPropertyNames.OwnerId] = new AttributeValue(partitionKey), [DynamoDbScoreDataPropertyNames.DataId] = new AttributeValue(DynamoDbScoreDataConstant.PrefixDescription + score + descriptionHash), }, ExpressionAttributeNames = new Dictionary <string, string>() { ["#content"] = DynamoDbScoreDataPropertyNames.Content, }, ProjectionExpression = "#content", }; try { var response = await client.GetItemAsync(request); if (!response.IsItemSet) { return(false, ""); } var description = response.Item[DynamoDbScoreDataPropertyNames.Content].S; return(true, description); } catch (Exception ex) { Console.WriteLine(ex.Message); throw; } }
public async Task ReplaceAnnotationsAsync(Guid ownerId, Guid scoreId, List <PatchScoreAnnotation> annotations) { if (annotations.Count == 0) { throw new ArgumentException(nameof(annotations)); } var(data, oldHash) = await GetAsync(_dynamoDbClient, ScoreTableName, ownerId, scoreId); data.Annotations ??= new List <DynamoDbScoreAnnotationV1>(); // Key id, Value index var annotationIndices = new Dictionary <long, int>(); foreach (var(ann, index) in data.Annotations.Select((x, index) => (x, index))) { annotationIndices[ann.Id] = index; } var replacingAnnotations = new List <(DynamoDbScoreAnnotationV1 data, int targetIndex)>(); var existedAnnData = new HashSet <string>(); data.Annotations.ForEach(x => existedAnnData.Add(x.ContentHash)); var addAnnData = new Dictionary <string, PatchScoreAnnotation>(); foreach (var ann in annotations) { var id = ann.TargetAnnotationId; if (!annotationIndices.TryGetValue(id, out var index)) { throw new InvalidOperationException(); } var hash = DynamoDbScoreDataUtils.CalcHash(DynamoDbScoreDataUtils.AnnotationPrefix, ann.Content); if (!existedAnnData.Contains(hash)) { addAnnData[hash] = ann; } var a = new DynamoDbScoreAnnotationV1() { Id = id, ContentHash = hash, }; replacingAnnotations.Add((a, index)); data.Annotations[index] = a; } var removeAnnData = existedAnnData.ToHashSet(); foreach (var annotation in data.Annotations) { if (removeAnnData.Contains(annotation.ContentHash)) { removeAnnData.Remove(annotation.ContentHash); } } var newHash = data.CalcDataHash(); var now = ScoreDatabaseUtils.UnixTimeMillisecondsNow(); await UpdateAsync(_dynamoDbClient, ScoreTableName, ownerId, scoreId, replacingAnnotations, newHash, oldHash, now); await AddAnnListAsync(_dynamoDbClient, ScoreDataTableName, ownerId, scoreId, addAnnData); await RemoveAnnListAsync(_dynamoDbClient, ScoreDataTableName, ownerId, scoreId, removeAnnData);