Skip to content

Commit b016091

Browse files
committed
Refactor server management and enhance bootstrapping process
- Adjusted BootstrapConfig struct for improved readability by aligning field declarations. - Introduced incremental server startup in BootstrapWithContext to allow users to access servers as they become ready. - Added StartMissing method in TmuxManager to ensure all servers are running, enhancing server management during provisioning. - Updated install wizard to utilize StartMissing for better server readiness feedback.
1 parent 618ca72 commit b016091

File tree

4 files changed

+65
-25
lines changed

4 files changed

+65
-25
lines changed

src/internal/csm/bootstrap.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ import (
1818
// BootstrapConfig mirrors the high-level options used by the original
1919
// bootstrap_cs2.sh script.
2020
type BootstrapConfig struct {
21-
CS2User string
22-
NumServers int
23-
BaseGamePort int
24-
BaseTVPort int
25-
EnableMetamod bool
26-
FreshInstall bool
21+
CS2User string
22+
NumServers int
23+
BaseGamePort int
24+
BaseTVPort int
25+
EnableMetamod bool
26+
FreshInstall bool
2727
// UpdateMaster controls how the master CS2 install is handled:
2828
// - true → run SteamCMD to install or update the master (fresh or in-place)
2929
// - false → reuse an existing master if present; fail if missing
@@ -191,6 +191,11 @@ func BootstrapWithContext(ctx context.Context, cfg BootstrapConfig) (string, err
191191
}
192192
}
193193

194+
// Start servers as soon as each instance is fully provisioned so large
195+
// installs become usable incrementally instead of waiting for all N
196+
// servers to be ready.
197+
mgr := &TmuxManager{CS2User: cfg.CS2User}
198+
194199
for i := 1; i <= cfg.NumServers; i++ {
195200
gamePort := cfg.BaseGamePort + (i-1)*10
196201
tvPort := cfg.BaseTVPort + (i-1)*10
@@ -218,6 +223,14 @@ func BootstrapWithContext(ctx context.Context, cfg BootstrapConfig) (string, err
218223
}
219224

220225
log(" [✓] Server-%d ready (port %d, TV %d)", i, gamePort, tvPort)
226+
227+
// Start this server immediately after it is ready so users can begin
228+
// using early servers while later ones are still provisioning.
229+
if err := mgr.Start(i); err != nil {
230+
log(" [!] Failed to start server-%d via tmux: %v", i, err)
231+
} else {
232+
log(" [✓] Server-%d started via tmux", i)
233+
}
221234
log("")
222235
}
223236

src/internal/csm/tmux.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,30 @@ func (m *TmuxManager) Status() (string, error) {
190190
return buf.String(), nil
191191
}
192192

193+
// StartMissing starts any servers that are currently stopped, leaving already
194+
// running tmux sessions untouched. This is used by flows like the install
195+
// wizard that may start servers incrementally during provisioning and only
196+
// need a final "ensure everything is running" pass.
197+
func (m *TmuxManager) StartMissing() error {
198+
if m.NumServers <= 0 {
199+
log.Printf("[tmux] StartMissing: no servers to start (NumServers=0, user=%q)", m.CS2User)
200+
return fmt.Errorf("no CS2 servers found; run the install wizard first")
201+
}
202+
log.Printf("[tmux] StartMissing: ensuring %d server(s) are running for user=%q", m.NumServers, m.CS2User)
203+
for i := 1; i <= m.NumServers; i++ {
204+
session := m.sessionName(i)
205+
cmd := m.runAsCS2User("tmux has-session -t " + session)
206+
if err := cmd.Run(); err == nil {
207+
// Session already exists and is running; skip.
208+
continue
209+
}
210+
if err := m.Start(i); err != nil {
211+
return err
212+
}
213+
}
214+
return nil
215+
}
216+
193217
// StartAll starts all servers (creating tmux sessions if needed).
194218
func (m *TmuxManager) StartAll() error {
195219
if m.NumServers <= 0 {

src/internal/tui/install_wizard.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -973,20 +973,20 @@ func runInstallStep(cfg installConfig, step installStep) tea.Cmd {
973973
// Derive MatchZy Docker behaviour from dbMode.
974974
cfg.matchzySkipDocker = strings.EqualFold(cfg.dbMode, "external")
975975
bcfg := csm.BootstrapConfig{
976-
CS2User: cfg.cs2User,
977-
NumServers: cfg.numServers,
978-
BaseGamePort: cfg.basePort,
979-
BaseTVPort: cfg.tvPort,
980-
EnableMetamod: cfg.enableMetamod,
981-
FreshInstall: cfg.freshInstall,
982-
UpdateMaster: cfg.updateMaster,
983-
RCONPassword: cfg.rconPassword,
984-
MatchzySkipDocker: cfg.matchzySkipDocker,
985-
DBMode: cfg.dbMode,
986-
ExternalDBHost: cfg.externalDBHost,
987-
ExternalDBPort: cfg.externalDBPort,
988-
ExternalDBName: cfg.externalDBName,
989-
ExternalDBUser: cfg.externalDBUser,
976+
CS2User: cfg.cs2User,
977+
NumServers: cfg.numServers,
978+
BaseGamePort: cfg.basePort,
979+
BaseTVPort: cfg.tvPort,
980+
EnableMetamod: cfg.enableMetamod,
981+
FreshInstall: cfg.freshInstall,
982+
UpdateMaster: cfg.updateMaster,
983+
RCONPassword: cfg.rconPassword,
984+
MatchzySkipDocker: cfg.matchzySkipDocker,
985+
DBMode: cfg.dbMode,
986+
ExternalDBHost: cfg.externalDBHost,
987+
ExternalDBPort: cfg.externalDBPort,
988+
ExternalDBName: cfg.externalDBName,
989+
ExternalDBUser: cfg.externalDBUser,
990990
ExternalDBPassword: cfg.externalDBPassword,
991991
}
992992

@@ -1065,7 +1065,7 @@ func runInstallStep(cfg installConfig, step installStep) tea.Cmd {
10651065
}
10661066

10671067
case installStepStartServers:
1068-
logs = append(logs, "[4/4] Starting all servers...")
1068+
logs = append(logs, "[4/4] Ensuring all servers are running...")
10691069
manager, err := csm.NewTmuxManager()
10701070
if err != nil {
10711071
logs = append(logs, fmt.Sprintf("Failed to initialize tmux manager: %v", err))
@@ -1075,15 +1075,15 @@ func runInstallStep(cfg installConfig, step installStep) tea.Cmd {
10751075
err: err,
10761076
}
10771077
}
1078-
if err := manager.StartAll(); err != nil {
1079-
logs = append(logs, fmt.Sprintf("Failed to start servers: %v", err))
1078+
if err := manager.StartMissing(); err != nil {
1079+
logs = append(logs, fmt.Sprintf("Failed to ensure servers are running: %v", err))
10801080
return installStepMsg{
10811081
step: installStepStartServers,
10821082
out: strings.Join(logs, "\n"),
10831083
err: err,
10841084
}
10851085
}
1086-
logs = append(logs, "[4/4] All servers started via tmux.")
1086+
logs = append(logs, "[4/4] All servers are running via tmux.")
10871087
dur := time.Since(start).Round(time.Second)
10881088
logs = append(logs, fmt.Sprintf("[i] Step 4/4 (start servers) took %s.", dur))
10891089
appendInstallLog(cfg, installStepStartServers, strings.Join(logs, "\n"))

src/internal/tui/model.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1141,7 +1141,10 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
11411141
}
11421142
m.currentInstallStep = installStepStartServers
11431143
m.installStepStart = time.Now()
1144-
m.installStatusBase = "Step 4/4: Starting all servers..."
1144+
// Step 4 starts any remaining stopped servers; most servers will
1145+
// already be running from the bootstrap step, so emphasise that
1146+
// we're just ensuring everything is up.
1147+
m.installStatusBase = "Step 4/4: Ensuring all servers are running..."
11451148
m.installExpected = "~10–60 seconds"
11461149
m.status = m.installStatusBase
11471150
return m, tea.Batch(append(cmds,

0 commit comments

Comments
 (0)