fix: clearer Club Log / FCC ULS upload-download diagnostics
Club Log: on a failed batch, log the callsign#id of every QSO in it so a per-record rejection (e.g. a field value nginx's WAF blocks with a 403) can actually be located instead of hiding behind "batch FAILED". FCC ULS: catch the maintenance bounce before following it. data.fcc.gov redirects to www.fcc.gov/system-maintenance during maintenance windows, and that page then HTTP/2-stream-errors — which surfaced as a cryptic INTERNAL_ERROR. Detect the redirect and return "try again later".
This commit is contained in:
@@ -7846,7 +7846,15 @@ func (a *App) runManualUpload(svc extsvc.Service, ids []int64, cfg extsvc.Extern
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
msg = err.Error()
|
msg = err.Error()
|
||||||
}
|
}
|
||||||
|
// Name the QSOs in the failing batch so a per-record rejection
|
||||||
|
// (e.g. a field value nginx's WAF blocks with a 403) can actually
|
||||||
|
// be located — otherwise "batch FAILED" hides which contact it is.
|
||||||
|
who := make([]string, 0, len(batch))
|
||||||
|
for _, it := range batch {
|
||||||
|
who = append(who, fmt.Sprintf("%s#%d", it.call, it.id))
|
||||||
|
}
|
||||||
emit(fmt.Sprintf("Club Log: batch of %d FAILED: %s", len(batch), msg))
|
emit(fmt.Sprintf("Club Log: batch of %d FAILED: %s", len(batch), msg))
|
||||||
|
applog.Printf("extsvc: Club Log batch FAILED (%s) — QSOs: %s", msg, strings.Join(who, ", "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+24
-1
@@ -24,6 +24,7 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
@@ -37,6 +38,10 @@ import (
|
|||||||
_ "modernc.org/sqlite"
|
_ "modernc.org/sqlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// errFCCMaintenance is raised when the FCC ULS download host bounces us to its
|
||||||
|
// maintenance page instead of serving the file (a frequent, FCC-side event).
|
||||||
|
var errFCCMaintenance = errors.New("fcc uls under maintenance")
|
||||||
|
|
||||||
// Default download URLs (overridable in Import for tests).
|
// Default download URLs (overridable in Import for tests).
|
||||||
const (
|
const (
|
||||||
fccAmateurURL = "https://data.fcc.gov/download/pub/uls/complete/l_amat.zip"
|
fccAmateurURL = "https://data.fcc.gov/download/pub/uls/complete/l_amat.zip"
|
||||||
@@ -325,8 +330,26 @@ func download(ctx context.Context, url, dest string, prog func(pct int)) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
resp, err := http.DefaultClient.Do(req)
|
// Catch the FCC maintenance bounce BEFORE following it: data.fcc.gov redirects
|
||||||
|
// to www.fcc.gov/system-maintenance during maintenance windows, and that page
|
||||||
|
// then HTTP/2-stream-errors — which surfaced as a cryptic "INTERNAL_ERROR"
|
||||||
|
// instead of a plain "try again later".
|
||||||
|
client := &http.Client{
|
||||||
|
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
||||||
|
if strings.Contains(r.URL.String(), "system-maintenance") {
|
||||||
|
return errFCCMaintenance
|
||||||
|
}
|
||||||
|
if len(via) >= 10 {
|
||||||
|
return errors.New("stopped after 10 redirects")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, errFCCMaintenance) || strings.Contains(err.Error(), "system-maintenance") {
|
||||||
|
return fmt.Errorf("the FCC ULS download service is under maintenance (fcc.gov redirected to its maintenance page) — please try again later")
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|||||||
Reference in New Issue
Block a user