Commit Graph

7 Commits

Author SHA1 Message Date
Houmgaor
8fe6f60813 fix(channelserver): add error logging to silently ignored repo calls
19 repository calls across 8 handler files were silently discarding
errors with `_ =`, making database failures invisible. Add structured
logging at appropriate levels: Error for write operations where data
loss may occur (guild saves, member updates), Warn for read operations
where handlers continue with zero-value defaults (application checks,
warehouse loads, item box queries). No control flow changes.
2026-02-21 17:37:29 +01:00
Houmgaor
6fbd294575 refactor(channelserver): eliminate *sql.Tx from repository interfaces
Hide transaction management inside repository implementations so
interfaces only expose domain types, enabling clean mocking and
decoupling handlers from PostgreSQL internals.

- Replace BeginTx + UpdateEventQuestStartTime with batch
  UpdateEventQuestStartTimes that manages its own transaction
- Remove tx parameter from CreateApplication, add composite
  CreateApplicationWithMail for atomic scout+mail operations
- Remove SendMailTx from MailRepo (sole caller migrated)
- Remove database/sql import from repo_interfaces.go
2026-02-21 14:56:59 +01:00
Houmgaor
de3bf9173a refactor(channelserver): extract RengokuRepository and MailRepository
Move all direct DB access from handlers_rengoku.go (11 calls) and
handlers_mail.go (10 calls) into dedicated repository types, continuing
the established extraction pattern.

RengokuRepository provides UpsertScore and GetRanking, replacing a
3-call check/insert/update sequence and an 8-case switch of nearly
identical queries respectively.

MailRepository provides SendMail, SendMailTx, GetListForCharacter,
GetByID, MarkRead, MarkDeleted, SetLocked, and MarkItemReceived.
The old Mail.Send(), Mail.MarkRead(), GetMailListForCharacter, and
GetMailByID free functions are removed. Guild handlers that sent mail
via Mail.Send(s, ...) now call mailRepo directly.
2026-02-20 23:31:27 +01:00
Houmgaor
96d07f1c04 refactor(channelserver): extract GuildRepository for guild table access
Per anti-patterns.md item #9, guild-related SQL was scattered across
~15 handler files with no repository abstraction. Following the same
pattern established by CharacterRepository, this centralizes all
guilds, guild_characters, and guild_applications table access into a
single GuildRepository (~30 methods).

guild_model.go and handlers_guild_member.go are trimmed to types and
pure business logic only. All handler files (guild_*, festa, mail,
house, mercenary, rengoku) now call s.server.guildRepo methods
instead of direct DB queries or methods on domain objects.
2026-02-20 22:06:55 +01:00
Houmgaor
d32e77efba refactor: replace panic calls with structured error handling
Replace ~25 panic() calls in non-fatal code paths with proper
s.logger.Error + return patterns. Panics in handler code crashed
goroutines (caught by defer/recover but still disruptive) instead
of failing gracefully.

Key changes:
- SJISToUTF8 now returns (string, error); all 30+ callers updated
- Handler DB/IO panics replaced with log + return/ack fail
- Unhandled switch-case panics replaced with logger.Error
- Sign server Accept() panic replaced with log + continue
- Dead unreachable panic in guild_model.go removed
- deltacomp patch error logs and returns partial data

Panics intentionally kept: ByteFrame sentinel, unimplemented
packet stubs, os.Exit in main.go.
2026-02-20 19:11:41 +01:00
Houmgaor
754b5a3bff feat(channelserver): decouple channel servers for independent operation (#33)
Enable multiple Erupe instances to share a single PostgreSQL database
without destroying each other's state, fix existing data races in
cross-channel access, and lay groundwork for future distributed
channel server deployments.

Phase 1 — DB safety:
- Scope DELETE FROM servers/sign_sessions to this instance's server IDs
- Fix ci++ bug where failed channel start shifted subsequent IDs

Phase 2 — Fix data races in cross-channel access:
- Lock sessions map in FindSessionByCharID and DisconnectUser
- Lock stagesLock in handleMsgSysLockGlobalSema
- Snapshot sessions/stages under lock in TransitMessage types 1-4
- Lock channel when finding mail notification targets

Phase 3 — ChannelRegistry interface:
- Define ChannelRegistry interface with 7 cross-channel operations
- Implement LocalChannelRegistry with proper locking
- Add SessionSnapshot/StageSnapshot immutable copy types
- Delegate WorldcastMHF, FindSessionByCharID, DisconnectUser to Registry
- Migrate LockGlobalSema and guild mail handlers to use Registry
- Add comprehensive tests including concurrent access

Phase 4 — Per-channel enable/disable:
- Add Enabled *bool to EntranceChannelInfo (nil defaults to true)
- Skip disabled channels in startup loop, preserving ID stability
- Add IsEnabled() helper with backward-compatible default
- Update config.example.json with Enabled field
2026-02-19 18:13:34 +01:00
Houmgaor
35665a46d8 refactor(channelserver): split handlers_guild.go into sub-files
handlers_guild.go was 2090 lines mixing unrelated guild subsystems.
Extract handlers into focused files following the existing pattern:

- handlers_guild_ops.go: OperateGuild switch + member operations
- handlers_guild_info.go: InfoGuild + EnumerateGuild display
- handlers_guild_mission.go: guild mission system
- handlers_guild_cooking.go: meals, weekly bonus, hunt data
- handlers_guild_board.go: message board system

Core types, methods, and DB functions remain in handlers_guild.go
(now ~1000 lines).
2026-02-18 00:19:11 +01:00