mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-05-06 14:24:15 +02:00
fix(gacha): log and skip gacha_items rows that fail to scan
Previously GetItemsForEntry/GetGuaranteedItems silently swallowed StructScan errors, so misconfigured rows (item_type > 255 or item_id/quantity > 65535) disappeared from rewards with no trace, making config bugs hard to diagnose without a DB dump. Pass a zap.Logger into GachaRepository and emit a Warn pointing at the likely cause and the offending entry/gacha ID.
This commit is contained in:
@@ -6,17 +6,22 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GachaRepository centralizes all database access for gacha-related tables
|
// GachaRepository centralizes all database access for gacha-related tables
|
||||||
// (gacha_shop, gacha_entries, gacha_items, gacha_stepup, gacha_box).
|
// (gacha_shop, gacha_entries, gacha_items, gacha_stepup, gacha_box).
|
||||||
type GachaRepository struct {
|
type GachaRepository struct {
|
||||||
db *sqlx.DB
|
db *sqlx.DB
|
||||||
|
logger *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGachaRepository creates a new GachaRepository.
|
// NewGachaRepository creates a new GachaRepository.
|
||||||
func NewGachaRepository(db *sqlx.DB) *GachaRepository {
|
func NewGachaRepository(db *sqlx.DB, logger *zap.Logger) *GachaRepository {
|
||||||
return &GachaRepository{db: db}
|
if logger == nil {
|
||||||
|
logger = zap.NewNop()
|
||||||
|
}
|
||||||
|
return &GachaRepository{db: db, logger: logger}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEntryForTransaction reads the cost type/amount and roll count for a gacha transaction.
|
// GetEntryForTransaction reads the cost type/amount and roll count for a gacha transaction.
|
||||||
@@ -65,9 +70,12 @@ func (r *GachaRepository) GetItemsForEntry(entryID uint32) ([]GachaItem, error)
|
|||||||
defer func() { _ = rows.Close() }()
|
defer func() { _ = rows.Close() }()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var item GachaItem
|
var item GachaItem
|
||||||
if err := rows.StructScan(&item); err == nil {
|
if err := rows.StructScan(&item); err != nil {
|
||||||
items = append(items, item)
|
r.logger.Warn("Skipping gacha_items row that failed to scan — check item_type (≤255) and item_id/quantity (≤65535) for out-of-range values",
|
||||||
|
zap.Uint32("entryID", entryID), zap.Error(err))
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
items = append(items, item)
|
||||||
}
|
}
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
@@ -85,9 +93,12 @@ func (r *GachaRepository) GetGuaranteedItems(rollType uint8, gachaID uint32) ([]
|
|||||||
defer func() { _ = rows.Close() }()
|
defer func() { _ = rows.Close() }()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var item GachaItem
|
var item GachaItem
|
||||||
if err := rows.StructScan(&item); err == nil {
|
if err := rows.StructScan(&item); err != nil {
|
||||||
items = append(items, item)
|
r.logger.Warn("Skipping guaranteed gacha_items row that failed to scan — check item_type (≤255) and item_id/quantity (≤65535) for out-of-range values",
|
||||||
|
zap.Uint8("rollType", rollType), zap.Uint32("gachaID", gachaID), zap.Error(err))
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
items = append(items, item)
|
||||||
}
|
}
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ func setupGachaRepo(t *testing.T) (*GachaRepository, *sqlx.DB, uint32) {
|
|||||||
db := SetupTestDB(t)
|
db := SetupTestDB(t)
|
||||||
userID := CreateTestUser(t, db, "gacha_test_user")
|
userID := CreateTestUser(t, db, "gacha_test_user")
|
||||||
charID := CreateTestCharacter(t, db, userID, "GachaChar")
|
charID := CreateTestCharacter(t, db, userID, "GachaChar")
|
||||||
repo := NewGachaRepository(db)
|
repo := NewGachaRepository(db, nil)
|
||||||
t.Cleanup(func() { TeardownTestDB(t, db) })
|
t.Cleanup(func() { TeardownTestDB(t, db) })
|
||||||
return repo, db, charID
|
return repo, db, charID
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -581,7 +581,7 @@ func createTestServerWithDB(t *testing.T, db *sqlx.DB) *Server {
|
|||||||
server.charRepo = NewCharacterRepository(db)
|
server.charRepo = NewCharacterRepository(db)
|
||||||
server.guildRepo = NewGuildRepository(db)
|
server.guildRepo = NewGuildRepository(db)
|
||||||
server.userRepo = NewUserRepository(db)
|
server.userRepo = NewUserRepository(db)
|
||||||
server.gachaRepo = NewGachaRepository(db)
|
server.gachaRepo = NewGachaRepository(db, nil)
|
||||||
server.houseRepo = NewHouseRepository(db)
|
server.houseRepo = NewHouseRepository(db)
|
||||||
server.festaRepo = NewFestaRepository(db)
|
server.festaRepo = NewFestaRepository(db)
|
||||||
server.towerRepo = NewTowerRepository(db)
|
server.towerRepo = NewTowerRepository(db)
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ func NewServer(config *Config) *Server {
|
|||||||
s.charRepo = NewCharacterRepository(config.DB)
|
s.charRepo = NewCharacterRepository(config.DB)
|
||||||
s.guildRepo = NewGuildRepository(config.DB)
|
s.guildRepo = NewGuildRepository(config.DB)
|
||||||
s.userRepo = NewUserRepository(config.DB)
|
s.userRepo = NewUserRepository(config.DB)
|
||||||
s.gachaRepo = NewGachaRepository(config.DB)
|
s.gachaRepo = NewGachaRepository(config.DB, s.logger)
|
||||||
s.houseRepo = NewHouseRepository(config.DB)
|
s.houseRepo = NewHouseRepository(config.DB)
|
||||||
s.festaRepo = NewFestaRepository(config.DB)
|
s.festaRepo = NewFestaRepository(config.DB)
|
||||||
s.towerRepo = NewTowerRepository(config.DB)
|
s.towerRepo = NewTowerRepository(config.DB)
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ func SetTestDB(s *Server, db *sqlx.DB) {
|
|||||||
s.charRepo = NewCharacterRepository(db)
|
s.charRepo = NewCharacterRepository(db)
|
||||||
s.guildRepo = NewGuildRepository(db)
|
s.guildRepo = NewGuildRepository(db)
|
||||||
s.userRepo = NewUserRepository(db)
|
s.userRepo = NewUserRepository(db)
|
||||||
s.gachaRepo = NewGachaRepository(db)
|
s.gachaRepo = NewGachaRepository(db, nil)
|
||||||
s.houseRepo = NewHouseRepository(db)
|
s.houseRepo = NewHouseRepository(db)
|
||||||
s.festaRepo = NewFestaRepository(db)
|
s.festaRepo = NewFestaRepository(db)
|
||||||
s.towerRepo = NewTowerRepository(db)
|
s.towerRepo = NewTowerRepository(db)
|
||||||
|
|||||||
Reference in New Issue
Block a user