99 "fmt"
1010 "io"
1111 "net/http"
12+ "os"
1213 "regexp"
1314 "strconv"
1415 "strings"
@@ -247,11 +248,24 @@ func (c *Client) Close() {
247248
248249// createTables creates the DXCC tables if they don't exist.
249250func (c * Client ) createTables () error {
250- // First, drop existing tables to ensure new schema
251- dropQueries := []string {
252- fmt .Sprintf ("DROP TABLE IF EXISTS %s" , prefixesTableName ),
253- fmt .Sprintf ("DROP TABLE IF EXISTS %s" , exceptionsTableName ),
254- fmt .Sprintf ("DROP TABLE IF EXISTS %s" , entitiesTableName ),
251+ // Only drop tables if DXCC_FORCE_REBUILD environment variable is set
252+ // This prevents data loss on every restart while allowing schema updates when needed
253+ forceRebuild := os .Getenv ("DXCC_FORCE_REBUILD" ) == "true" || os .Getenv ("DXCC_FORCE_REBUILD" ) == "1"
254+
255+ if forceRebuild {
256+ logging .Warn ("DXCC_FORCE_REBUILD is set - dropping existing tables to rebuild schema" )
257+ dropQueries := []string {
258+ fmt .Sprintf ("DROP TABLE IF EXISTS %s" , prefixesTableName ),
259+ fmt .Sprintf ("DROP TABLE IF EXISTS %s" , exceptionsTableName ),
260+ fmt .Sprintf ("DROP TABLE IF EXISTS %s" , entitiesTableName ),
261+ }
262+
263+ db := c .dbClient .GetDB ()
264+ for _ , query := range dropQueries {
265+ if _ , err := db .Exec (query ); err != nil {
266+ return fmt .Errorf ("failed to drop table: %w\n Query: %s" , err , query )
267+ }
268+ }
255269 }
256270
257271 queries := []string {
@@ -311,13 +325,6 @@ func (c *Client) createTables() error {
311325
312326 db := c .dbClient .GetDB ()
313327
314- // Drop existing tables first
315- for _ , query := range dropQueries {
316- if _ , err := db .Exec (query ); err != nil {
317- return fmt .Errorf ("failed to drop table: %w\n Query: %s" , err , query )
318- }
319- }
320-
321328 // Create new tables with updated schema
322329 for _ , query := range queries {
323330 if _ , err := db .Exec (query ); err != nil {
@@ -522,9 +529,9 @@ func (c *Client) loadMapsFromDB(ctx context.Context) error {
522529 exceptionCount := len (c .exceptionsMap )
523530 entityCount := len (c .entitiesMap )
524531
525- // Only log at INFO level if we actually have data, otherwise use DEBUG
532+ // Only log at NOTICE level if we actually have data, otherwise use DEBUG
526533 if prefixCount > 0 || exceptionCount > 0 || entityCount > 0 {
527- logging .Info ("DXCC data loaded: %d prefixes, %d exceptions, %d entities." , prefixCount , exceptionCount , entityCount )
534+ logging .Notice ("DXCC data loaded: %d prefixes, %d exceptions, %d entities." , prefixCount , exceptionCount , entityCount )
528535 } else {
529536 logging .Debug ("DXCC data loaded: %d prefixes, %d exceptions, %d entities (empty - will check for updates)." , prefixCount , exceptionCount , entityCount )
530537 }
@@ -537,30 +544,14 @@ func (c *Client) loadMapsFromDB(ctx context.Context) error {
537544}
538545
539546// StartUpdater starts the periodic update job for DXCC data.
547+ // Note: Does NOT perform an initial check - main.go handles that synchronously before calling this.
540548func (c * Client ) StartUpdater (ctx context.Context ) {
541549 if c .updateStop != nil {
542550 return // already running
543551 }
544552 c .updateStop = make (chan struct {})
545553 c .updateDone = make (chan struct {})
546554
547- // Check if initial update is needed
548- go func () {
549- needsUpdate , err := c .needsUpdate (ctx )
550- if err != nil {
551- logging .Error ("Failed to check if DXCC data needs update: %v" , err )
552- // Fallback to update on error
553- needsUpdate = true
554- }
555-
556- if needsUpdate {
557- logging .Info ("DXCC data needs update, fetching..." )
558- c .fetchAndStoreData (ctx )
559- } else {
560- logging .Info ("DXCC data is up to date, skipping initial download" )
561- }
562- }()
563-
564555 go func () {
565556 ticker := time .NewTicker (c .cfg .DXCCUpdateInterval )
566557 defer ticker .Stop ()
@@ -577,7 +568,7 @@ func (c *Client) StartUpdater(ctx context.Context) {
577568 }
578569 }
579570 }()
580- logging .Info ("DXCC updater started. Will check for updates every %s." , c .cfg .DXCCUpdateInterval )
571+ logging .Notice ("DXCC updater started. Will check for updates every %s." , c .cfg .DXCCUpdateInterval )
581572}
582573
583574// fetchAndStoreData downloads the cty.xml.gz, parses it, and replaces data in the database.
@@ -652,7 +643,7 @@ func (c *Client) fetchAndStoreData(ctx context.Context) {
652643 logging .Error ("Both Club Log and GitHub DXCC downloads failed after retries: %v" , err )
653644 return
654645 }
655- logging .Info ("Successfully downloaded DXCC data from GitHub fallback." )
646+ logging .Notice ("Successfully downloaded DXCC data from GitHub fallback." )
656647 // Debug: show a small diagnostic about the fetched payload to help tests
657648 gz := false
658649 if len (data ) >= 2 && data [0 ] == 0x1f && data [1 ] == 0x8b {
@@ -668,7 +659,7 @@ func (c *Client) fetchAndStoreData(ctx context.Context) {
668659 }
669660 logging .Debug ("DXCC fallback download diagnostics: bytes=%d gzipped=%t head=%q" , len (data ), gz , head )
670661 } else {
671- logging .Info ("Successfully downloaded DXCC data from Club Log." )
662+ logging .Notice ("Successfully downloaded DXCC data from Club Log." )
672663 }
673664
674665 xmlData , err := c .decompressAndParseXML (data )
0 commit comments