refactor: IndexNow request batches and answer outcome as functions

No behaviour change: NotifyIndexNow splits through indexNowBatches and
SendIndexNow maps the answer through indexNowOutcome, so both can be unit
tested without a queue or the network.
This commit is contained in:
Jakub Zych
2026-11-04 19:34:09 +01:00
parent 096b6f6bfe
commit ae70567e63

View File

@@ -142,15 +142,24 @@ func NotifyIndexNow(ctx context.Context, app *backpack.App, db *gorm.DB, res Reb
if err != nil {
return err
}
for start := 0; start < len(urls); start += MaxIndexNowURLs {
end := min(start+MaxIndexNowURLs, len(urls))
if err := m.Enqueue(ctx, db, IndexNowArgs{URLs: urls[start:end]}, conga.EnqueueOpts{}); err != nil {
for _, batch := range indexNowBatches(urls) {
if err := m.Enqueue(ctx, db, IndexNowArgs{URLs: batch}, conga.EnqueueOpts{}); err != nil {
return err
}
}
return nil
}
// indexNowBatches splits urls into requests of at most MaxIndexNowURLs, in
// order.
func indexNowBatches(urls []string) [][]string {
var out [][]string
for start := 0; start < len(urls); start += MaxIndexNowURLs {
out = append(out, urls[start:min(start+MaxIndexNowURLs, len(urls))])
}
return out
}
// indexNowBody is the JSON of an IndexNow request. keyLocation is not sent:
// the key file is served at the site root, which covers every address of
// the host (P33-14).
@@ -214,11 +223,11 @@ func SendIndexNow(ctx context.Context, app *backpack.App, args IndexNowArgs) err
time.Now().UTC(), len(urls), status).Error; err != nil {
return err
}
switch {
case status == http.StatusOK || status == http.StatusAccepted:
switch indexNowOutcome(status) {
case indexNowSent:
pluginLog.Info("golem15.sitemap: indexnow notified", "urls", len(urls), "status", status)
return nil
case status == http.StatusTooManyRequests || status >= 500:
case indexNowRetry:
pluginLog.Warn("golem15.sitemap: indexnow will retry", "urls", len(urls), "status", status)
return errIndexNowRetry{status: status}
default:
@@ -227,6 +236,26 @@ func SendIndexNow(ctx context.Context, app *backpack.App, args IndexNowArgs) err
}
}
// The outcomes of an IndexNow answer.
const (
indexNowSent = iota
indexNowRetry
indexNowRefused
)
// indexNowOutcome maps an IndexNow answer's status: 200 and 202 are sent,
// 429 and 5xx are retried, everything else (400, 403, 422) is refused and
// not retried.
func indexNowOutcome(status int) int {
switch {
case status == http.StatusOK || status == http.StatusAccepted:
return indexNowSent
case status == http.StatusTooManyRequests || status >= 500:
return indexNowRetry
}
return indexNowRefused
}
// EnsureKey gives settings row 1 an IndexNow key on save: while enabled,
// a new key is generated when none is stored or rotate is set (the
// indexnow_new_key checkbox), so the old key file answers 404 at once. It