public async Task <NewlyScore> CreateAsync(Guid ownerId, NewScore newScore) { var title = newScore.Title; var description = newScore.Description; if (title == null) { throw new ArgumentNullException(nameof(newScore)); } var preprocessingTitle = title.Trim(); if (preprocessingTitle == "") { throw new ArgumentException(nameof(newScore)); } if (_quota.TitleLengthMax < preprocessingTitle.Length) { throw new ArgumentException(nameof(newScore)); } var preprocessingDescription = description?.Trim(); if (_quota.DescriptionLengthMax < preprocessingDescription?.Length) { throw new ArgumentException(nameof(newScore)); } var newScoreId = _commonLogic.NewGuid(); return(await CreateAsync(ownerId, newScoreId, preprocessingTitle, preprocessingDescription)); }
public async Task InitializeScoreAsync(Guid ownerId) { var partitionKey = PartitionPrefix.Score + _commonLogic.ConvertIdFromGuid(ownerId); var newLockValue = _commonLogic.NewGuid(); var newLock = _commonLogic.ConvertIdFromGuid(newLockValue); await PutAsync(_dynamoDbClient, ScoreTableName, partitionKey, newLock);
public async Task DeleteMainAsync(Guid ownerId, Guid scoreId) { var partitionKey = PartitionPrefix.Score + _commonLogic.ConvertIdFromGuid(ownerId); var score = _commonLogic.ConvertIdFromGuid(scoreId); var newLockSummary = _commonLogic.NewGuid(); var newLockSummaryValue = _commonLogic.ConvertIdFromGuid(newLockSummary); var actions = new List <TransactWriteItem>() { new() { Delete = new Delete() { Key = new Dictionary <string, AttributeValue>() {
public async Task AddAnnotationsInnerAsync(Guid ownerId, Guid scoreId, List <NewScoreAnnotation> annotations) { if (annotations.Count == 0) { throw new ArgumentException(nameof(annotations)); } var(oldAnnotations, oldAnnotationCount, oldLock, existedChunks) = await GetAsync(ownerId, scoreId); var sortedIds = oldAnnotations.OrderBy(x => x.Id).Select(x => x.Id).ToArray(); long next = 0; int idIndex = 0; long NewId() { for (; idIndex < sortedIds.Length; ++idIndex, ++next) { var id = sortedIds[idIndex]; if (next == id) { continue; } return(next++); } return(next++); } var annotationOnMains = new List <AnnotationOnMain>(); var annotationOnDatas = new List <AnnotationOnData>(); foreach (var annotation in annotations) { var id = NewId(); annotationOnMains.Add(new AnnotationOnMain() { Id = id, Length = annotation.Content.Length, }); annotationOnDatas.Add(new AnnotationOnData() { Id = id, Content = annotation.Content, }); } var now = _commonLogic.Now; var timeout = now.AddSeconds(10); // このリクエスト処理を完了しなければならない時間 // timeout と同じ時間にしないのは次のリクエストとアノテーションデータ更新部分 (UpdateAnnotationsAsync) が // 確実に並列に実行されないことを保証するため var processTimeout = now.AddSeconds(5); var newLock = _commonLogic.NewGuid(); var annotationCountMax = _quota.AnnotationCountMax; var newAnnotationCount = annotations.Count; var existedChunkSet = new HashSet <string>(existedChunks.Distinct()); await TransactionStartAndCheckAsync( ownerId, scoreId, oldLock, newLock, now, timeout, annotationCountMax, newAnnotationCount); await UpdateAnnotationsAsync(ownerId, scoreId, existedChunkSet, annotationOnDatas, processTimeout); var now2 = _commonLogic.Now; if (processTimeout <= now2) { // アノテーションデータの保存に時間がかかりタイムアウトが発生するまでに処理が終わっていない場合 // 次のリクエストで来ている可能性があるのでこのリクエストは失敗とする throw new InvalidOperationException("timeout"); } var newLock2 = _commonLogic.NewGuid(); await UpdateMainAndTransactionCommitAsync( ownerId, scoreId, annotationOnMains, newLock, newLock2, now2, annotationCountMax); }