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

Ensure rank cache is correctly updated when joining tournaments.

parent e6306860
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr
- Ensure group count does not update when failing to add a member.
- Handle Google IAP validation token caching when using credential overrides.
- More graceful handling of no-op authoritative storage delete operations.
- Ensure rank cache is correctly updated when joining tournaments.

## [3.14.0] - 2022-10-14
### Added
+1 −1
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ func (s *ApiServer) JoinTournament(ctx context.Context, in *api.JoinTournamentRe

	tournamentID := in.GetTournamentId()

	if err := TournamentJoin(ctx, s.logger, s.db, s.leaderboardCache, userID.String(), username, tournamentID); err != nil {
	if err := TournamentJoin(ctx, s.logger, s.db, s.leaderboardCache, s.leaderboardRankCache, userID, username, tournamentID); err != nil {
		if err == runtime.ErrTournamentNotFound {
			return nil, status.Error(codes.NotFound, "Tournament not found.")
		} else if err == runtime.ErrTournamentMaxSizeReached {
+12 −4
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ func TournamentAddAttempt(ctx context.Context, logger *zap.Logger, db *sql.DB, c
	return nil
}

func TournamentJoin(ctx context.Context, logger *zap.Logger, db *sql.DB, cache LeaderboardCache, owner, username, tournamentId string) error {
func TournamentJoin(ctx context.Context, logger *zap.Logger, db *sql.DB, cache LeaderboardCache, rankCache LeaderboardRankCache, ownerID uuid.UUID, username, tournamentId string) error {
	leaderboard := cache.Get(tournamentId)
	if leaderboard == nil {
		// If it does not exist treat it as success.
@@ -136,13 +136,14 @@ func TournamentJoin(ctx context.Context, logger *zap.Logger, db *sql.DB, cache L
		return err
	}

	var isNewJoin bool
	if err = ExecuteInTx(ctx, tx, func() error {
		query := `INSERT INTO leaderboard_record
(leaderboard_id, owner_id, expiry_time, username, num_score, max_num_score)
VALUES
($1, $2, $3, $4, $5, $6)
ON CONFLICT(owner_id, leaderboard_id, expiry_time) DO NOTHING`
		result, err := tx.ExecContext(ctx, query, tournamentId, owner, time.Unix(expiryTime, 0).UTC(), username, 0, leaderboard.MaxNumScore)
		result, err := tx.ExecContext(ctx, query, tournamentId, ownerID.String(), time.Unix(expiryTime, 0).UTC(), username, 0, leaderboard.MaxNumScore)
		if err != nil {
			return err
		}
@@ -169,17 +170,24 @@ ON CONFLICT(owner_id, leaderboard_id, expiry_time) DO NOTHING`
			}
		}

		isNewJoin = true

		return nil
	}); err != nil {
		if err == runtime.ErrTournamentMaxSizeReached {
			logger.Info("Failed to join tournament, reached max size allowed.", zap.String("tournament_id", tournamentId), zap.String("owner", owner), zap.String("username", username))
			logger.Info("Failed to join tournament, reached max size allowed.", zap.String("tournament_id", tournamentId), zap.String("owner", ownerID.String()), zap.String("username", username))
			return err
		}
		logger.Error("Could not join tournament.", zap.Error(err))
		return err
	}

	logger.Info("Joined tournament.", zap.String("tournament_id", tournamentId), zap.String("owner", owner), zap.String("username", username))
	// Ensure new tournament joiner is included in the rank cache.
	if isNewJoin {
		_ = rankCache.Insert(leaderboard.Id, expiryTime, leaderboard.SortOrder, ownerID, 0, 0)
	}

	logger.Info("Joined tournament.", zap.String("tournament_id", tournamentId), zap.String("owner", ownerID.String()), zap.String("username", username))
	return nil
}

+4 −2
Original line number Diff line number Diff line
@@ -2567,7 +2567,9 @@ func (n *RuntimeGoNakamaModule) TournamentJoin(ctx context.Context, id, ownerID,

	if ownerID == "" {
		return errors.New("expects a owner ID string")
	} else if _, err := uuid.FromString(ownerID); err != nil {
	}
	oid, err := uuid.FromString(ownerID)
	if err != nil {
		return errors.New("expects owner ID to be a valid identifier")
	}

@@ -2575,7 +2577,7 @@ func (n *RuntimeGoNakamaModule) TournamentJoin(ctx context.Context, id, ownerID,
		return errors.New("expects a username string")
	}

	return TournamentJoin(ctx, n.logger, n.db, n.leaderboardCache, ownerID, username, id)
	return TournamentJoin(ctx, n.logger, n.db, n.leaderboardCache, n.leaderboardRankCache, oid, username, id)
}

// @group tournaments
+4 −2
Original line number Diff line number Diff line
@@ -5956,7 +5956,9 @@ func (n *runtimeJavascriptNakamaModule) tournamentJoin(r *goja.Runtime) func(goj
		userID := getJsString(r, f.Argument(1))
		if userID == "" {
			panic(r.NewTypeError("expects a user ID string"))
		} else if _, err := uuid.FromString(userID); err != nil {
		}
		uid, err := uuid.FromString(userID)
		if err != nil {
			panic(r.NewTypeError("expects user ID to be a valid identifier"))
		}

@@ -5965,7 +5967,7 @@ func (n *runtimeJavascriptNakamaModule) tournamentJoin(r *goja.Runtime) func(goj
			panic(r.NewTypeError("expects a username string"))
		}

		if err := TournamentJoin(n.ctx, n.logger, n.db, n.leaderboardCache, userID, username, id); err != nil {
		if err := TournamentJoin(n.ctx, n.logger, n.db, n.leaderboardCache, n.rankCache, uid, username, id); err != nil {
			panic(r.NewGoError(fmt.Errorf("error joining tournament: %v", err.Error())))
		}

Loading