Files
Erupe/server/channelserver/repo_guild_rp.go
Houmgaor 59fd722d37 refactor(channelserver): standardize on BeginTxx for all repository transactions
Replace db.Begin() with db.BeginTxx(context.Background(), nil) across all
8 remaining call sites in repo_guild.go, repo_guild_rp.go, repo_festa.go,
and repo_event.go. Use deferred Rollback() instead of explicit rollback
at each error return, eliminating 15 manual rollback calls.
2026-02-22 16:55:59 +01:00

103 lines
3.4 KiB
Go

package channelserver
import (
"context"
"time"
)
// AddMemberDailyRP adds RP to a member's daily total.
func (r *GuildRepository) AddMemberDailyRP(charID uint32, amount uint16) error {
_, err := r.db.Exec(`UPDATE guild_characters SET rp_today=rp_today+$1 WHERE character_id=$2`, amount, charID)
return err
}
// ExchangeEventRP subtracts RP from a guild's event pool and returns the new balance.
func (r *GuildRepository) ExchangeEventRP(guildID uint32, amount uint16) (uint32, error) {
var balance uint32
err := r.db.QueryRow(`UPDATE guilds SET event_rp=event_rp-$1 WHERE id=$2 RETURNING event_rp`, amount, guildID).Scan(&balance)
return balance, err
}
// AddRankRP adds RP to a guild's rank total.
func (r *GuildRepository) AddRankRP(guildID uint32, amount uint16) error {
_, err := r.db.Exec(`UPDATE guilds SET rank_rp = rank_rp + $1 WHERE id = $2`, amount, guildID)
return err
}
// AddEventRP adds RP to a guild's event total.
func (r *GuildRepository) AddEventRP(guildID uint32, amount uint16) error {
_, err := r.db.Exec(`UPDATE guilds SET event_rp = event_rp + $1 WHERE id = $2`, amount, guildID)
return err
}
// GetRoomRP returns the current room RP for a guild.
func (r *GuildRepository) GetRoomRP(guildID uint32) (uint16, error) {
var rp uint16
err := r.db.QueryRow(`SELECT room_rp FROM guilds WHERE id = $1`, guildID).Scan(&rp)
return rp, err
}
// SetRoomRP sets the room RP for a guild.
func (r *GuildRepository) SetRoomRP(guildID uint32, rp uint16) error {
_, err := r.db.Exec(`UPDATE guilds SET room_rp = $1 WHERE id = $2`, rp, guildID)
return err
}
// AddRoomRP atomically adds RP to a guild's room total.
func (r *GuildRepository) AddRoomRP(guildID uint32, amount uint16) error {
_, err := r.db.Exec(`UPDATE guilds SET room_rp = room_rp + $1 WHERE id = $2`, amount, guildID)
return err
}
// SetRoomExpiry sets the room expiry time for a guild.
func (r *GuildRepository) SetRoomExpiry(guildID uint32, expiry time.Time) error {
_, err := r.db.Exec(`UPDATE guilds SET room_expiry = $1 WHERE id = $2`, expiry, guildID)
return err
}
// RolloverDailyRP moves rp_today into rp_yesterday for all members of a guild,
// then updates the guild's rp_reset_at timestamp.
// Uses SELECT FOR UPDATE to prevent concurrent rollovers from racing.
func (r *GuildRepository) RolloverDailyRP(guildID uint32, noon time.Time) error {
tx, err := r.db.BeginTxx(context.Background(), nil)
if err != nil {
return err
}
defer func() { _ = tx.Rollback() }()
// Lock the guild row and re-check whether rollover is still needed.
var rpResetAt time.Time
if err := tx.QueryRow(
`SELECT COALESCE(rp_reset_at, '2000-01-01'::timestamptz) FROM guilds WHERE id = $1 FOR UPDATE`,
guildID,
).Scan(&rpResetAt); err != nil {
return err
}
if !rpResetAt.Before(noon) {
// Another goroutine already rolled over; nothing to do.
return nil
}
if _, err := tx.Exec(
`UPDATE guild_characters SET rp_yesterday = rp_today, rp_today = 0 WHERE guild_id = $1`,
guildID,
); err != nil {
return err
}
if _, err := tx.Exec(
`UPDATE guilds SET rp_reset_at = $1 WHERE id = $2`,
noon, guildID,
); err != nil {
return err
}
return tx.Commit()
}
// AddWeeklyBonusUsers atomically adds numUsers to the guild's weekly bonus exceptional user count.
func (r *GuildRepository) AddWeeklyBonusUsers(guildID uint32, numUsers uint8) error {
_, err := r.db.Exec(
"UPDATE guilds SET weekly_bonus_users = weekly_bonus_users + $1 WHERE id = $2",
numUsers, guildID,
)
return err
}