feat: skip leadership wait for rqlite nodes with existing state and add ports 4002/5002 to clear script

This commit is contained in:
anonpenguin 2025-08-09 08:45:47 +03:00
parent 355c1c66b9
commit a38cc08809
2 changed files with 27 additions and 5 deletions

View File

@ -10,7 +10,7 @@ set -euo pipefail
# Collect ports from args or use defaults # Collect ports from args or use defaults
PORTS=("$@") PORTS=("$@")
if [ ${#PORTS[@]} -eq 0 ]; then if [ ${#PORTS[@]} -eq 0 ]; then
PORTS=(4001 5001 7001 7002) PORTS=(4001 4002 5001 5002 7001 7002)
fi fi
echo "Gracefully terminating listeners on: ${PORTS[*]}" echo "Gracefully terminating listeners on: ${PORTS[*]}"

View File

@ -139,11 +139,17 @@ func (r *RQLiteManager) Start(ctx context.Context) error {
} }
r.connection = conn r.connection = conn
// Wait for RQLite to establish leadership (for bootstrap nodes) // Wait for RQLite to establish leadership (only on fresh bootstrap)
if r.config.RQLiteJoinAddress == "" { if r.config.RQLiteJoinAddress == "" {
if err := r.waitForLeadership(ctx); err != nil { if !r.hasExistingState(rqliteDataDir) {
r.cmd.Process.Kill() if err := r.waitForLeadership(ctx); err != nil {
return fmt.Errorf("RQLite failed to establish leadership: %w", err) r.cmd.Process.Kill()
return fmt.Errorf("RQLite failed to establish leadership: %w", err)
}
} else {
// Existing state implies this node may be part of a multi-voter cluster; quorum may be required.
// Do not fail startup if leadership is not immediately available.
r.logger.Info("Existing Raft state detected; skipping leadership wait (cluster may require quorum)")
} }
} }
@ -151,6 +157,22 @@ func (r *RQLiteManager) Start(ctx context.Context) error {
return nil return nil
} }
// hasExistingState returns true if the rqlite data directory already contains files or subdirectories.
func (r *RQLiteManager) hasExistingState(rqliteDataDir string) bool {
entries, err := os.ReadDir(rqliteDataDir)
if err != nil {
return false
}
for _, e := range entries {
// Any existing file or directory indicates prior state
if e.Name() == "." || e.Name() == ".." {
continue
}
return true
}
return false
}
// waitForReady waits for RQLite to be ready to accept connections // waitForReady waits for RQLite to be ready to accept connections
func (r *RQLiteManager) waitForReady(ctx context.Context) error { func (r *RQLiteManager) waitForReady(ctx context.Context) error {
url := fmt.Sprintf("http://localhost:%d/status", r.config.RQLitePort) url := fmt.Sprintf("http://localhost:%d/status", r.config.RQLitePort)