mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-26 09:33:02 +01:00
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
This commit is contained in:
@@ -297,6 +297,15 @@ type EntranceChannelInfo struct {
|
||||
Port uint16
|
||||
MaxPlayers uint16
|
||||
CurrentPlayers uint16
|
||||
Enabled *bool // nil defaults to true for backward compatibility
|
||||
}
|
||||
|
||||
// IsEnabled returns whether this channel is enabled. Defaults to true if Enabled is nil.
|
||||
func (c *EntranceChannelInfo) IsEnabled() bool {
|
||||
if c.Enabled == nil {
|
||||
return true
|
||||
}
|
||||
return *c.Enabled
|
||||
}
|
||||
|
||||
var ErupeConfig *Config
|
||||
|
||||
@@ -536,6 +536,34 @@ func TestEntranceChannelInfo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestEntranceChannelInfoIsEnabled tests the Enabled field and IsEnabled helper
|
||||
func TestEntranceChannelInfoIsEnabled(t *testing.T) {
|
||||
trueVal := true
|
||||
falseVal := false
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
enabled *bool
|
||||
want bool
|
||||
}{
|
||||
{"nil defaults to true", nil, true},
|
||||
{"explicit true", &trueVal, true},
|
||||
{"explicit false", &falseVal, false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
info := EntranceChannelInfo{
|
||||
Port: 10001,
|
||||
Enabled: tt.enabled,
|
||||
}
|
||||
if got := info.IsEnabled(); got != tt.want {
|
||||
t.Errorf("IsEnabled() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestDiscord verifies Discord struct
|
||||
func TestDiscord(t *testing.T) {
|
||||
discord := Discord{
|
||||
|
||||
Reference in New Issue
Block a user