This commit is contained in:
2026-06-10 20:27:44 +02:00
parent 42b5c6247d
commit 6150498a9e
9 changed files with 223 additions and 120 deletions
+32 -15
View File
@@ -576,7 +576,7 @@ func (a *App) startup(ctx context.Context) {
a.dxcc = dxcc.NewManager(dataDir)
a.lookup.SetDXCCResolver(dxccAdapter{m: a.dxcc})
go func() {
if err := a.dxcc.EnsureLoaded(context.Background()); err != nil {
if err := a.dxcc.EnsureLoaded(a.ctx); err != nil {
fmt.Println("OpsLog: cty.dat unavailable —", err)
return
}
@@ -847,6 +847,19 @@ func (a *App) runBackupForShutdown() error {
return a.settings.Set(a.ctx, keyBackupLast, time.Now().UTC().Format(time.RFC3339))
}
// setSetting persists a key/value and logs (rather than silently swallows) a
// failure — used for non-critical settings writes where the caller can't
// surface the error but a lost write would still mislead (stale timestamps,
// seed markers…).
func (a *App) setSetting(key, val string) {
if a.settings == nil {
return
}
if err := a.settings.Set(a.ctx, key, val); err != nil {
applog.Printf("settings: set %q failed: %v", key, err)
}
}
func (a *App) shutdown(ctx context.Context) {
// If the user managed to skip beforeClose (force kill, OS shutdown,
// crash recovery) we still try the backup here as a best-effort
@@ -1503,13 +1516,13 @@ func (a *App) migrateAwardDefs() {
changed = true
}
}
_ = a.settings.Set(a.ctx, keyAwardDefsFixed, defsFixVersion)
a.setSetting(keyAwardDefsFixed, defsFixVersion)
}
if !changed {
return
}
if b, err := json.Marshal(migrated); err == nil {
_ = a.settings.Set(a.ctx, keyAwardDefs, string(b))
a.setSetting(keyAwardDefs, string(b))
applog.Printf("awards: migrated/fixed %d definitions", len(migrated))
}
}
@@ -1843,12 +1856,10 @@ func (a *App) SyncPOTAHunterLog(addMissing bool, onlyMyCall bool) (POTASyncResul
case emptyBest >= 0:
all[emptyBest].POTARef = e.Reference // stamp regardless of time skew
toUpdate[emptyBest] = struct{}{}
res.Updated++
case nonEmptyBest >= 0 && nonEmptyDiff <= nferWindow:
// n-fer: same physical QSO at another park.
all[nonEmptyBest].POTARef += "," + e.Reference
toUpdate[nonEmptyBest] = struct{}{}
res.Updated++
case len(byCall[pota.BaseCall(e.Worked)]) == 0 && addMissing:
toAdd = append(toAdd, e)
default:
@@ -1857,8 +1868,14 @@ func (a *App) SyncPOTAHunterLog(addMissing bool, onlyMyCall bool) (POTASyncResul
}
}
// Count only QSOs actually written, and log failures — so the report
// reflects reality (a DB lock / constraint no longer inflates "updated").
for i := range toUpdate {
_ = a.qso.Update(a.ctx, all[i])
if err := a.qso.Update(a.ctx, all[i]); err != nil {
applog.Printf("pota: update QSO %s failed: %v", all[i].Callsign, err)
continue
}
res.Updated++
}
if len(toAdd) > 0 {
res.Added = a.insertPOTAQSOs(toAdd)
@@ -2330,7 +2347,7 @@ func (a *App) UpdateAwardReferenceList(code string) (AwardRefMeta, error) {
}
now := time.Now().Format("2006-01-02 15:04")
if a.settings != nil {
_ = a.settings.Set(a.ctx, keyAwardRefsUpdated+strings.ToUpper(code), now)
a.setSetting(keyAwardRefsUpdated+strings.ToUpper(code), now)
}
applog.Printf("award-refs: %s updated — %d references", strings.ToUpper(code), n)
return AwardRefMeta{Code: strings.ToUpper(code), Count: n, UpdatedAt: now, CanUpdate: true}, nil
@@ -2380,7 +2397,7 @@ func (a *App) ReplaceAwardReferences(code string, refs []awardref.Ref) (int, err
return 0, err
}
if a.settings != nil {
_ = a.settings.Set(a.ctx, keyAwardRefsUpdated+strings.ToUpper(code), time.Now().Format("2006-01-02 15:04"))
a.setSetting(keyAwardRefsUpdated+strings.ToUpper(code), time.Now().Format("2006-01-02 15:04"))
}
return n, nil
}
@@ -2592,7 +2609,7 @@ func (a *App) seedBuiltinReferences() {
}
}
}
_ = a.settings.Set(a.ctx, keyAwardRefsSeeded, builtinRefsVersion)
a.setSetting(keyAwardRefsSeeded, builtinRefsVersion)
}
// ImportAwardReferencesText parses pasted lines or CSV into references and
@@ -4448,7 +4465,7 @@ func (a *App) runManualUpload(svc extsvc.Service, ids []int64, cfg extsvc.Extern
wruntime.EventsEmit(a.ctx, "qslmgr:log", line)
}
}
ctx := context.Background()
ctx := a.ctx
uploaded := 0
if svc == extsvc.ServiceLoTW {
@@ -4555,7 +4572,7 @@ func (a *App) runDownloadConfirmations(svc extsvc.Service, cfg extsvc.ExternalSe
wruntime.EventsEmit(a.ctx, "qslmgr:done", map[string]any{"uploaded": matched, "total": total})
}
}
ctx := context.Background()
ctx := a.ctx
matched, total, added := 0, 0, 0
// resolveSince turns the UI's request into a concrete date (or ""):
@@ -4674,7 +4691,7 @@ func (a *App) runDownloadConfirmations(svc extsvc.Service, cfg extsvc.ExternalSe
}
// Remember today so the next pull is incremental (per active profile).
if a.settings != nil {
_ = a.settings.Set(ctx, a.profileScope()+keyExtLoTWLastDownload, time.Now().UTC().Format("2006-01-02"))
a.setSetting(a.profileScope()+keyExtLoTWLastDownload, time.Now().UTC().Format("2006-01-02"))
}
case extsvc.ServiceQRZ:
@@ -4702,7 +4719,7 @@ func (a *App) runDownloadConfirmations(svc extsvc.Service, cfg extsvc.ExternalSe
// late meant the date was never saved, so "since last download" kept
// resolving to empty and re-pulled everything.
if a.settings != nil {
_ = a.settings.Set(ctx, a.profileScope()+keyExtQRZLastDownload, time.Now().UTC().Format("2006-01-02"))
a.setSetting(a.profileScope()+keyExtQRZLastDownload, time.Now().UTC().Format("2006-01-02"))
}
if snip := strings.TrimSpace(adifText); snip != "" {
if len(snip) > 300 {
@@ -5507,7 +5524,7 @@ func (a *App) RunBackupNow() (string, error) {
if err != nil {
return path, err
}
_ = a.settings.Set(a.ctx, keyBackupLast, time.Now().UTC().Format(time.RFC3339))
a.setSetting(keyBackupLast, time.Now().UTC().Format(time.RFC3339))
return path, nil
}
@@ -5535,7 +5552,7 @@ func (a *App) maybeShutdownBackup() {
fmt.Println("OpsLog: shutdown backup failed:", err)
return
}
_ = a.settings.Set(a.ctx, keyBackupLast, time.Now().UTC().Format(time.RFC3339))
a.setSetting(keyBackupLast, time.Now().UTC().Format(time.RFC3339))
}
// PickBackupFolder opens a native directory picker so the user can browse