public async Task <Stream> ConvertToUtf(ScoreMeta scoreMeta) { var memStream = new MemoryStream(); var option = new JsonSerializerOptions() { }; await JsonSerializer.SerializeAsync(memStream, scoreMeta, option); memStream.Position = 0; return(memStream); }
public async Task <IActionResult> CreateScoreAsync( [FromRoute(Name = "score_name")] string scoreName, [FromBody] PatchScore patchScore) { var convertor = new ScoreMetaConvertor(); var metaFileOperator = new MetaFileOperator(S3Client, BucketName); var key = $"{scoreName}/{ScoreMeta.FileName}"; ScoreMeta scoreMeta; try { scoreMeta = await metaFileOperator.GetScoreMetaAsync(scoreName); } catch (AmazonS3Exception e) { Logger.LogError(e, e.Message); throw; } var newCurrentScoreMeta = convertor.ConvertToContent(scoreMeta.GetLastScoreContent(), patchScore); var newScoreMetaKey = ScoreMeta.CreateKey(); scoreMeta[newScoreMetaKey] = newCurrentScoreMeta; try { await metaFileOperator.SaveScoreMetaAsync(scoreName, scoreMeta, newScoreMetaKey); } catch (Exception e) { Logger.LogError(e, e.Message); throw; } return(Ok()); }
public async Task <IActionResult> CreateVersion( [FromRoute(Name = "score_name")] string scoreName, [FromForm] NewScoreVersion newScoreVersion) { var metaFileOperator = new MetaFileOperator(S3Client, BucketName); var images = newScoreVersion.Images; var nosText = newScoreVersion.Nos; var keyCount = images.GroupBy(x => x.FileName, x => x) .Select(x => (filename: x.Key, count: x.Count())) .Where(x => 2 <= x.count) .ToImmutableArray(); if (keyCount.Any()) { var errorMessage = string.Join(Environment.NewLine, new string[] { "次のファイルが重複しています" }.Concat(keyCount.Select(x => $"'{x.filename}'"))); throw new InvalidOperationException(errorMessage); } var nos = JsonSerializer.Deserialize <Dictionary <string, double> >(nosText); var notContainsNos = images.Select(x => x.FileName) .Where(x => !nos.ContainsKey(x)) .ToImmutableArray(); if (notContainsNos.Any()) { var errorMessage = string.Join(Environment.NewLine, new string[] { "次のファイルの No が指定されていません" }.Concat(notContainsNos.Select(x => $"'{x}'"))); throw new InvalidOperationException(errorMessage); } var now = DateTimeOffset.UtcNow; var nextVersion = await metaFileOperator.NewVersionNumber(scoreName); var versionFileKey = metaFileOperator.CreateVersionFileKey(scoreName, nextVersion, now); var versionMeta = new ScoreVersionMeta() { Version = int.Parse(nextVersion), }; foreach (var formFile in images) { var no = nos[formFile.FileName].ToString("F").TrimEnd('0').TrimEnd('.'); var commentPrefix = metaFileOperator.CreatePageCommentPrefix(scoreName, nextVersion, now, no); try { var key = await metaFileOperator.SaveImage(scoreName, formFile); versionMeta.Pages[no] = new ScoreVersionPageMeta() { No = no, ImageFileKey = key, CommentPrefix = commentPrefix, }; } catch (AmazonS3Exception e) { Logger.LogError(e, e.Message); throw; } } await metaFileOperator.SaveVersionMetaAsync(versionFileKey, versionMeta); var scoreMeta = await metaFileOperator.GetScoreMetaAsync(scoreName); var scoreContentMeta = await scoreMeta.GetLastScoreContent().DeepCopyAsync(); scoreContentMeta.VersionFileKeys[nextVersion] = versionFileKey; var scoreMetaKey = ScoreMeta.CreateKey(); scoreMeta[scoreMetaKey] = scoreContentMeta; await metaFileOperator.SaveScoreMetaAsync(scoreName, scoreMeta, scoreMetaKey); return(Ok()); }
public async Task SaveScoreMetaAsync(string scoreName, ScoreMeta scoreMeta, string metaKey) { var convertor = new ScoreMetaConvertor(); var key = $"{scoreName}/{ScoreMeta.FileName}"; int retryCount = 5; for (int i = 0; i < retryCount; i++) { try { var stream = await convertor.ConvertToUtf(scoreMeta); var putRequest = new PutObjectRequest { BucketName = BucketName, Key = key, InputStream = stream, CannedACL = S3CannedACL.PublicRead, }; await this.S3Client.PutObjectAsync(putRequest); } catch (AmazonS3Exception) { // Error throw; } try { var request = new GetObjectRequest { BucketName = BucketName, Key = key, }; var response = await this.S3Client.GetObjectAsync(request); var stream = response.ResponseStream; var checkedMeta = await convertor.ConvertToScoreMeta(stream); // 同一のキーが登録される可能性があるがキーには少数3桁の時間を指定してるので // ほぼキーが重なる自体はないと考える // もしキーの重複が問題になる用であれば内容の比較も行う if (checkedMeta.ContainsKey(metaKey)) { return; } } catch (AmazonS3Exception) { // skip } if (i < (retryCount - 1)) { Thread.Sleep(2000); } } throw new InvalidOperationException("追加更新に失敗しました"); }