fix: log returns as soon as the QSO row is inserted; award_refs/recording/uploads/eQSL now run off the critical path (both manual and UDP) — a busy multi-op MySQL no longer freezes the entry form ~40s waiting on the award_refs UPDATE
This commit is contained in:
@@ -1948,25 +1948,36 @@ func (a *App) AddQSO(q qso.QSO) (id int64, err error) {
|
|||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
q.ID = id
|
q.ID = id
|
||||||
a.noteWorked(q.Callsign, q.Band, q.Mode) // keep the alert worked-index fresh
|
a.noteWorked(q.Callsign, q.Band, q.Mode) // keep the alert worked-index fresh (in-memory)
|
||||||
a.noteLiveQSO() // multi-op: flip this operator back "online"
|
a.noteLiveQSO() // multi-op: flip this operator back "online" (publishes async)
|
||||||
a.materializeAwardRefs(q) // stamp award_refs so the grid columns show at once
|
// Announce the log RIGHT AWAY so the grid/UI refresh at once and the entry
|
||||||
// Announce the log so UI widgets can react (e.g. the Flex panel zeroing RIT).
|
// form clears immediately — the operator is not made to wait on the DB.
|
||||||
wruntime.EventsEmit(a.ctx, "qso:logged", id)
|
wruntime.EventsEmit(a.ctx, "qso:logged", id)
|
||||||
a.saveQSORecording(&q)
|
// Everything below writes to (or reads from) the shared DB. Run it OFF the
|
||||||
if a.extsvc != nil {
|
// critical path: on a busy multi-op MySQL the award_refs UPDATE alone could
|
||||||
a.extsvc.OnQSOLogged(id)
|
// block ~40s (and hit "Too many connections"), which used to freeze the log
|
||||||
}
|
// (form stuck, "…" on the button) until it finished. The QSO row is already
|
||||||
a.maybeAutoSendEQSL(q)
|
// safely inserted; these just enrich it, so they can lag a beat.
|
||||||
// Forward the ADIF of this QSO to any outbound "ADIF message" UDP rows.
|
qc := q
|
||||||
if a.udp != nil {
|
go func() {
|
||||||
go a.udp.EmitLoggedADIF(adif.SingleRecordADIF(q))
|
a.materializeAwardRefs(qc) // fills the award_refs column
|
||||||
}
|
a.saveQSORecording(&qc)
|
||||||
// A successful write means the link is healthy again — if QSOs are still
|
if a.extsvc != nil {
|
||||||
// parked, get them in now rather than waiting for the next tick.
|
a.extsvc.OnQSOLogged(id)
|
||||||
if a.offlineMode && a.offlineQ != nil && a.offlineQ.Count() > 0 {
|
}
|
||||||
go func() { _, _ = a.replayOfflineQueue() }()
|
a.maybeAutoSendEQSL(qc)
|
||||||
}
|
if a.udp != nil {
|
||||||
|
a.udp.EmitLoggedADIF(adif.SingleRecordADIF(qc))
|
||||||
|
}
|
||||||
|
// Nudge the grid again so the award_refs columns appear once materialised.
|
||||||
|
if a.ctx != nil {
|
||||||
|
wruntime.EventsEmit(a.ctx, "qso:logged", id)
|
||||||
|
}
|
||||||
|
// A successful write means the link is healthy — flush any parked QSOs.
|
||||||
|
if a.offlineMode && a.offlineQ != nil && a.offlineQ.Count() > 0 {
|
||||||
|
_, _ = a.replayOfflineQueue()
|
||||||
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
return id, err
|
return id, err
|
||||||
}
|
}
|
||||||
@@ -9634,24 +9645,28 @@ func (a *App) LogUDPLoggedADIF(adifText string) (int64, error) {
|
|||||||
return 0, fmt.Errorf("insert qso: %w", err)
|
return 0, fmt.Errorf("insert qso: %w", err)
|
||||||
}
|
}
|
||||||
q.ID = id
|
q.ID = id
|
||||||
a.noteLiveQSO() // multi-op: flip this operator back "online"
|
a.noteLiveQSO() // multi-op: flip this operator back "online" (publishes async)
|
||||||
a.materializeAwardRefs(q)
|
// Announce the log AT ONCE so the grid / ON-AIR badge / stations-on-air widget
|
||||||
// Announce the log so UI widgets refresh AT ONCE (the Recent-QSOs grid, the
|
// refresh immediately, then run the DB-heavy enrichment off the critical path
|
||||||
// ON-AIR badge and the "stations on air" widget). The manual log path always
|
// (same reasoning as the manual path — award_refs on a busy shared MySQL blocked).
|
||||||
// did this; the UDP/FT8 path did not, so a station running MSHV saw the top
|
|
||||||
// "on air" list lag ~15-45s behind the instant bottom badge.
|
|
||||||
if a.ctx != nil {
|
if a.ctx != nil {
|
||||||
wruntime.EventsEmit(a.ctx, "qso:logged", id)
|
wruntime.EventsEmit(a.ctx, "qso:logged", id)
|
||||||
}
|
}
|
||||||
a.saveQSORecording(&q)
|
qc := q
|
||||||
if a.extsvc != nil {
|
go func() {
|
||||||
a.extsvc.OnQSOLogged(id)
|
a.materializeAwardRefs(qc)
|
||||||
}
|
a.saveQSORecording(&qc)
|
||||||
a.maybeAutoSendEQSL(q)
|
if a.extsvc != nil {
|
||||||
// A successful write means the link is healthy again — flush anything parked.
|
a.extsvc.OnQSOLogged(id)
|
||||||
if a.offlineMode && a.offlineQ != nil && a.offlineQ.Count() > 0 {
|
}
|
||||||
go func() { _, _ = a.replayOfflineQueue() }()
|
a.maybeAutoSendEQSL(qc)
|
||||||
}
|
if a.ctx != nil {
|
||||||
|
wruntime.EventsEmit(a.ctx, "qso:logged", id) // refresh again so award_refs show
|
||||||
|
}
|
||||||
|
if a.offlineMode && a.offlineQ != nil && a.offlineQ.Count() > 0 {
|
||||||
|
_, _ = a.replayOfflineQueue()
|
||||||
|
}
|
||||||
|
}()
|
||||||
return id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user