Skip to content

Commit 0bc1314

Browse files
committed
DX Cluster race condition fixed
1 parent 66dea0b commit 0bc1314

1 file changed

Lines changed: 20 additions & 14 deletions

File tree

cmd/dxcluster-client/main.go

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ func RunApplication(ctx context.Context, args []string) int {
102102
}
103103
}
104104

105-
logging.Info("Starting %s v%s (+%s)", version.ProjectName, version.ProjectVersion, version.ProjectGitHubURL)
106-
logging.Info("User-Agent: %s", version.UserAgent)
105+
logging.Notice("Starting %s v%s (+%s)", version.ProjectName, version.ProjectVersion, version.ProjectGitHubURL)
106+
logging.Notice("User-Agent: %s", version.UserAgent)
107107

108108
ctx, cancel := context.WithCancel(ctx)
109109
defer cancel()
@@ -142,31 +142,31 @@ func RunApplication(ctx context.Context, args []string) int {
142142
}
143143

144144
// LOG_LEVEL was applied earlier so subsequent logs respect the selected level.
145-
logging.Info("Configuration loaded. WebPort: %d, MaxCache: %d, DataDir: %s", cfg.WebPort, cfg.MaxCache, cfg.DataDir)
145+
logging.Notice("Configuration loaded. WebPort: %d, MaxCache: %d, DataDir: %s", cfg.WebPort, cfg.MaxCache, cfg.DataDir)
146146

147147
// Debug configuration details
148148
logging.Debug("CLUSTERS JSON: '%s'", cfg.RawClustersJSON)
149149
logging.Debug("Global Callsign: '%s'", cfg.Callsign)
150150

151151
if len(cfg.Clusters) > 0 {
152-
logging.Info("DX Clusters configured: %d", len(cfg.Clusters))
152+
logging.Notice("DX Clusters configured: %d", len(cfg.Clusters))
153153
for i, cluster := range cfg.Clusters {
154154
sotaFlag := "no"
155155
if cluster.SOTA {
156156
sotaFlag = "yes"
157157
}
158-
logging.Info(" Cluster %d: %s:%s callsign=%s sota=%s", i+1, cluster.Host, cluster.Port, cluster.Callsign, sotaFlag)
158+
logging.Notice(" Cluster %d: %s:%s callsign=%s sota=%s", i+1, cluster.Host, cluster.Port, cluster.Callsign, sotaFlag)
159159
}
160160
} else {
161161
logging.Warn("No DX Clusters configured.")
162162
}
163163
if cfg.EnablePOTA {
164-
logging.Info("POTA integration enabled. Polling interval: %s", cfg.POTAPollInterval)
164+
logging.Notice("POTA integration enabled. Polling interval: %s", cfg.POTAPollInterval)
165165
} else {
166166
logging.Info("POTA integration disabled.")
167167
}
168168
if cfg.Redis.Enabled {
169-
logging.Info("Redis cache enabled. Host: %s:%s, DB: %d, TLS: %t", cfg.Redis.Host, cfg.Redis.Port, cfg.Redis.DB, cfg.Redis.UseTLS)
169+
logging.Notice("Redis cache enabled. Host: %s:%s, DB: %d, TLS: %t", cfg.Redis.Host, cfg.Redis.Port, cfg.Redis.DB, cfg.Redis.UseTLS)
170170
} else {
171171
logging.Info("Redis cache disabled (using in-memory).")
172172
}
@@ -191,7 +191,7 @@ func RunApplication(ctx context.Context, args []string) int {
191191
log.Fatalf("FATAL: Failed to initialize Redis client: %v\n", err)
192192
}
193193
defer rdb.Close()
194-
logging.Info("Redis client initialized and connected.")
194+
logging.Notice("Redis client initialized and connected.")
195195
}
196196

197197
// --- 3. Initialize LoTW Client ---
@@ -207,7 +207,7 @@ func RunApplication(ctx context.Context, args []string) int {
207207
}
208208

209209
// Perform initial synchronous LoTW data check and download BEFORE starting spot sources
210-
logging.Info("Checking LoTW data status...")
210+
logging.Notice("Checking LoTW data status...")
211211
lastLoTWUpdate, err := lotwClient.GetLastDownloadTime(ctx)
212212
if err != nil {
213213
logging.Warn("Failed to check LoTW last update time: %v", err)
@@ -244,7 +244,7 @@ func RunApplication(ctx context.Context, args []string) int {
244244
}
245245

246246
// Perform initial synchronous DXCC data check and download BEFORE starting spot sources
247-
logging.Info("Checking DXCC data status...")
247+
logging.Notice("Checking DXCC data status...")
248248
lastDXCCUpdate, err := dxccClient.GetLastDownloadTime(ctx)
249249
if err != nil {
250250
logging.Warn("Failed to check DXCC last update time: %v", err)
@@ -253,9 +253,9 @@ func RunApplication(ctx context.Context, args []string) int {
253253
if needsDXCCUpdate {
254254
logging.Info("DXCC data needs update, downloading now (this may take a moment)...")
255255
dxccClient.FetchAndStoreData(ctx)
256-
logging.Info("DXCC data downloaded and loaded successfully.")
256+
logging.Notice("DXCC data downloaded and loaded successfully.")
257257
} else {
258-
logging.Info("DXCC data is up to date (last updated: %s)", lastDXCCUpdate.Format(time.RFC3339))
258+
logging.Notice("DXCC data is up to date (last updated: %s)", lastDXCCUpdate.Format(time.RFC3339))
259259
// Load in-memory maps from database NOW to ensure they're ready before spots arrive
260260
if err := dxccClient.LoadMapsFromDB(ctx); err != nil {
261261
log.Fatalf("FATAL: Failed to load DXCC maps from database: %v\n", err)
@@ -264,7 +264,7 @@ func RunApplication(ctx context.Context, args []string) int {
264264
if len(dxccClient.PrefixesMap) == 0 {
265265
logging.Warn("DXCC database is empty despite recent update timestamp. Forcing download now...")
266266
dxccClient.FetchAndStoreData(ctx)
267-
logging.Info("DXCC data downloaded and loaded successfully after empty database detection.")
267+
logging.Notice("DXCC data downloaded and loaded successfully after empty database detection.")
268268
}
269269
}
270270

@@ -425,7 +425,13 @@ func RunApplication(ctx context.Context, args []string) int {
425425
select {
426426
case err := <-c.ErrorChan:
427427
if err != nil {
428-
logging.Error("from DX Cluster: %v", err)
428+
// Suppress "use of closed network connection" during graceful shutdown
429+
// This is expected when Close() is called while read loop is active
430+
if strings.Contains(err.Error(), "use of closed network connection") {
431+
logging.Debug("DX Cluster connection closed (expected during shutdown): %v", err)
432+
} else {
433+
logging.Error("from DX Cluster: %v", err)
434+
}
429435
}
430436
case msg := <-c.MessageChan:
431437
_ = msg // Ignore generic messages for now

0 commit comments

Comments
 (0)