Commit e4ddde59 authored by Andrei Mihu's avatar Andrei Mihu
Browse files

Fix handling of leaderboard record writes that do not need to update the database.

parent 5559e8f7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr
### Fixed
- Gracefully close Lua matches when call queue fills up.
- Better handling for Lua runtime wallet update operation errors.
- Fix handling of leaderboard record writes that do not need to update the database.

## [3.9.0] - 2021-10-29
### Added
+28 −5
Original line number Diff line number Diff line
@@ -465,6 +465,9 @@ func LeaderboardRecordWrite(ctx context.Context, logger *zap.Logger, db *sql.DB,
		params = append(params, scoreDelta, subscoreDelta)
	}

	// Track if the database record actually updates or not.
	var unchanged bool

	var dbUsername sql.NullString
	var dbScore int64
	var dbSubscore int64
@@ -475,15 +478,35 @@ func LeaderboardRecordWrite(ctx context.Context, logger *zap.Logger, db *sql.DB,
	var dbUpdateTime pgtype.Timestamptz

	if err := db.QueryRowContext(ctx, query, params...).Scan(&dbUsername, &dbScore, &dbSubscore, &dbNumScore, &dbMaxNumScore, &dbMetadata, &dbCreateTime, &dbUpdateTime); err != nil {
		if err != sql.ErrNoRows {
			logger.Error("Error writing leaderboard record", zap.Error(err))
			return nil, err
		}

	// ensure we have the latest dbscore, dbsubscore
	newRank := rankCache.Insert(leaderboardId, expiryTime, leaderboard.SortOrder, uuid.Must(uuid.FromString(ownerID)), dbScore, dbSubscore)
		// If no rows were returned then both of these criteria must have been met:
		// 1. There was already a record for this leaderboard, user, and expiry time.
		// 2. This new update did not meet the criteria to be stored, so no update
		//    occurred. For example the new entry was not better in a "best" leaderboard.
		// In this case the user's record is unchanged, and we can just read it as is.
		query = "SELECT username, score, subscore, num_score, max_num_score, metadata, create_time, update_time FROM leaderboard_record WHERE leaderboard_id = $1 AND owner_id = $2 AND expiry_time = $3"
		err = db.QueryRowContext(ctx, query, leaderboardId, ownerID, time.Unix(expiryTime, 0).UTC()).Scan(&dbUsername, &dbScore, &dbSubscore, &dbNumScore, &dbMaxNumScore, &dbMetadata, &dbCreateTime, &dbUpdateTime)
		if err != nil {
			logger.Error("Error after writing leaderboard record", zap.Error(err))
			return nil, err
		}
		unchanged = true
	}

	var rank int64
	if unchanged {
		rank = rankCache.Get(leaderboardId, expiryTime, uuid.Must(uuid.FromString(ownerID)))
	} else {
		// Ensure we have the latest dbscore, dbsubscore if there was an update.
		rank = rankCache.Insert(leaderboardId, expiryTime, leaderboard.SortOrder, uuid.Must(uuid.FromString(ownerID)), dbScore, dbSubscore)
	}

	record := &api.LeaderboardRecord{
		Rank:          newRank,
		Rank:          rank,
		LeaderboardId: leaderboardId,
		OwnerId:       ownerID,
		Score:         dbScore,