fix: serialise UDP QSO logging (lookup+dedup+insert) so multi-stream MSHV (4 QSOs at once) queues instead of firing concurrent lookups/DB writes that got 'too many requests'
This commit is contained in:
@@ -9455,6 +9455,15 @@ func (a *App) LogUDPLoggedADIF(adifText string) (int64, error) {
|
||||
if a.qso == nil {
|
||||
return 0, fmt.Errorf("db not initialized")
|
||||
}
|
||||
// Serialise the WHOLE operation — parse, callsign LOOKUP, dedup and insert —
|
||||
// so simultaneous UDP QSOs are processed one at a time (a queue). A multi-stream
|
||||
// MSHV finishing 4 QSOs at once used to fire 4 concurrent callsign lookups and DB
|
||||
// writes, which the QRZ/HamQTH service (and a remote DB) rejected with "too many
|
||||
// requests". Holding the lock across the lookup spaces them out; the UDP reader
|
||||
// runs on its own goroutine, so this never blocks packet reception — callers just
|
||||
// queue behind each other. (adifwatch shares this lock for the same reason.)
|
||||
a.udpLogMu.Lock()
|
||||
defer a.udpLogMu.Unlock()
|
||||
// Pull the first record out of the payload. WSJT-X / JTDX / MSHV
|
||||
// always send a single QSO per UDP packet (no header) but we tolerate
|
||||
// either form via adif.Parse.
|
||||
@@ -9597,12 +9606,10 @@ func (a *App) LogUDPLoggedADIF(adifText string) (int64, error) {
|
||||
// a minute (the two apps stamp their own time), so a minute-exact key
|
||||
// missed it and the contact got duplicated.
|
||||
//
|
||||
// The check + insert is guarded by udpLogMu: MSHV/WSJT can deliver the same
|
||||
// logged-QSO packet twice in quick succession (re-broadcast, or two
|
||||
// listeners), and without serialisation both goroutines read the dedup set
|
||||
// BEFORE either inserts, both pass, and the QSO lands twice.
|
||||
a.udpLogMu.Lock()
|
||||
defer a.udpLogMu.Unlock()
|
||||
// The check + insert is covered by udpLogMu (taken at the top of this function):
|
||||
// MSHV/WSJT can deliver the same logged-QSO packet twice in quick succession
|
||||
// (re-broadcast, or two listeners), and without serialisation both goroutines
|
||||
// read the dedup set BEFORE either inserts, both pass, and the QSO lands twice.
|
||||
seen, err := a.qso.ExistingDedupeKeys(a.ctx)
|
||||
if err == nil {
|
||||
base := q.QSODate.UTC()
|
||||
|
||||
Reference in New Issue
Block a user