From a0a71728a0d85a8742012cb6e5b757ec28116e8c Mon Sep 17 00:00:00 2001 From: KinjiKawaguchi Date: Tue, 2 Apr 2024 02:08:25 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20=E3=83=AA=E3=82=AF=E3=82=A8=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=83=9C=E3=83=87=E3=82=A3=E3=81=8B=E3=82=89=E6=83=85?= =?UTF-8?q?=E5=A0=B1=E3=82=92=E5=8F=96=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- typing-server/api/handler/score.go | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/typing-server/api/handler/score.go b/typing-server/api/handler/score.go index b061ab3..063d7d8 100644 --- a/typing-server/api/handler/score.go +++ b/typing-server/api/handler/score.go @@ -46,28 +46,26 @@ func GetScoresRanking(w http.ResponseWriter, r *http.Request) { func PostScore(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - userIDStr := r.URL.Query().Get("user_id") - userID, err := uuid.Parse(userIDStr) - if err != nil { - http.Error(w, "Invalid user_id", http.StatusBadRequest) - return + // リクエストボディから値を取得 + var requestBody struct { + UserID string `json:"user_id"` + Keystrokes int `json:"keystrokes"` + Accuracy float64 `json:"accuracy"` } - - keystrokesStr := r.URL.Query().Get("keystrokes") - keystrokes, err := strconv.Atoi(keystrokesStr) - if err != nil { - http.Error(w, "Invalid keystrokes", http.StatusBadRequest) + if err := json.NewDecoder(r.Body).Decode(&requestBody); err != nil { + http.Error(w, "Invalid request body", http.StatusBadRequest) return } - accuracyStr := r.URL.Query().Get("accuracy") - accuracy, err := strconv.ParseFloat(accuracyStr, 64) + // user_idをUUIDに変換 + userID, err := uuid.Parse(requestBody.UserID) if err != nil { - http.Error(w, "Invalid accuracy", http.StatusBadRequest) + http.Error(w, "Invalid user_id", http.StatusBadRequest) return } - if err := service.CreateScore(ctx, entClient, userID, keystrokes, accuracy); err != nil { + // スコアを作成 + if err := service.CreateScore(ctx, entClient, userID, requestBody.Keystrokes, requestBody.Accuracy); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } From 2a052b141646e99914757641e05ddbe17f505a37 Mon Sep 17 00:00:00 2001 From: KinjiKawaguchi Date: Wed, 3 Apr 2024 10:35:51 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20=E3=82=B9=E3=82=B3=E3=82=A2=E7=99=BB?= =?UTF-8?q?=E9=8C=B2=E3=81=8C=E6=AD=A3=E3=81=97=E3=81=8F=E3=82=B5=E3=82=8C?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- typing-server/api/repository/score.go | 70 ++++++++++++++++++++------- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/typing-server/api/repository/score.go b/typing-server/api/repository/score.go index aa6ff5a..417449c 100644 --- a/typing-server/api/repository/score.go +++ b/typing-server/api/repository/score.go @@ -90,10 +90,20 @@ func GetScoresRanking(ctx context.Context, client *ent.Client, sortBy string, st return rankings, nil } - func CreateScore(ctx context.Context, client *ent.Client, userID uuid.UUID, keystrokes int, accuracy float64) error { - // Create a new score - createdScore, err := client.Score.Create(). + // トランザクションを開始 + tx, err := client.Tx(ctx) + if err != nil { + return err + } + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + + // 新しいスコアを作成 + createdScore, err := tx.Score.Create(). SetKeystrokes(keystrokes). SetAccuracy(accuracy). SetUserID(userID). @@ -102,46 +112,70 @@ func CreateScore(ctx context.Context, client *ent.Client, userID uuid.UUID, keys return err } + // キーストロークと精度のチェック if keystrokes < 120 || accuracy < 0.95 { - return nil + return tx.Commit() + } + + // ユーザーを取得 + user, err := tx.User.Query().Where(user.ID(userID)).Only(ctx) + if err != nil { + return err + } + + // 最大キーストロークと最大精度のスコアを取得 + maxKeystrokeScore, maxAccuracyScore, err := getMaxScores(ctx, user) + if err != nil { + return err } - // Get the user - user, err := client.User.Query().Where(user.ID(userID)).Only(ctx) + // 以前の最大スコアのフラグを更新 + err = updateMaxScoreFlags(ctx, maxKeystrokeScore, maxAccuracyScore, createdScore) if err != nil { return err } - // Check if the new score has the maximum keystrokes + // トランザクションをコミット + return tx.Commit() +} + +func getMaxScores(ctx context.Context, user *ent.User) (*ent.Score, *ent.Score, error) { + // 最大キーストロークのスコアを取得 maxKeystrokeScore, err := user.QueryScores().Where(score.IsMaxKeystrokes(true)).Only(ctx) if err != nil && !ent.IsNotFound(err) { - return err + return nil, nil, err } - isMaxKeystrokes := maxKeystrokeScore == nil || createdScore.Keystrokes >= maxKeystrokeScore.Keystrokes - // Check if the new score has the maximum accuracy + // 最大精度のスコアを取得 maxAccuracyScore, err := user.QueryScores().Where(score.IsMaxAccuracy(true)).Only(ctx) if err != nil && !ent.IsNotFound(err) { - return err + return nil, nil, err } + + return maxKeystrokeScore, maxAccuracyScore, nil +} + +func updateMaxScoreFlags(ctx context.Context, maxKeystrokeScore, maxAccuracyScore, createdScore *ent.Score) error { + isMaxKeystrokes := maxKeystrokeScore == nil || createdScore.Keystrokes >= maxKeystrokeScore.Keystrokes isMaxAccuracy := maxAccuracyScore == nil || createdScore.Accuracy >= maxAccuracyScore.Accuracy - // Update the flags of the previous maximum scores - if maxKeystrokeScore != nil && !isMaxKeystrokes { - err = maxKeystrokeScore.Update().SetIsMaxKeystrokes(false).Exec(ctx) + // 以前の最大スコアのフラグを更新 + if maxKeystrokeScore != nil && isMaxKeystrokes { + err := maxKeystrokeScore.Update().SetIsMaxKeystrokes(false).Exec(ctx) if err != nil { return err } } - if maxAccuracyScore != nil && !isMaxAccuracy { - err = maxAccuracyScore.Update().SetIsMaxAccuracy(false).Exec(ctx) + + if maxAccuracyScore != nil && isMaxAccuracy { + err := maxAccuracyScore.Update().SetIsMaxAccuracy(false).Exec(ctx) if err != nil { return err } } - // Update the score with the maximum flags - err = createdScore.Update(). + // 作成したスコアの最大フラグを更新 + err := createdScore.Update(). SetIsMaxKeystrokes(isMaxKeystrokes). SetIsMaxAccuracy(isMaxAccuracy). Exec(ctx) From b942040e49d43944287933225b2097de2e1bc14b Mon Sep 17 00:00:00 2001 From: KinjiKawaguchi Date: Wed, 3 Apr 2024 10:40:35 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=E3=83=AD=E3=83=BC=E3=83=AB=E3=83=90?= =?UTF-8?q?=E3=83=83=E3=82=AF=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- typing-server/api/repository/score.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/typing-server/api/repository/score.go b/typing-server/api/repository/score.go index 417449c..fadff4b 100644 --- a/typing-server/api/repository/score.go +++ b/typing-server/api/repository/score.go @@ -2,6 +2,7 @@ package repository import ( "context" + "database/sql" "fmt" "github.com/google/uuid" @@ -97,8 +98,15 @@ func CreateScore(ctx context.Context, client *ent.Client, userID uuid.UUID, keys return err } defer func() { - if r := recover(); r != nil { - tx.Rollback() + // txがコミット済みの場合はロールバックしない + if tx == nil { + return + } + if err := tx.Rollback(); err != nil { + if err != sql.ErrTxDone { + return + } + return } }()