Приём отвечает 200 до свёртки, свёртку ведёт фоновый воркер
- Очередью служит сама таблица: доставка ждёт свёртки в статусе `pending`, канал несёт только бит «есть работа». Переполнять нечего, падение процесса очередь не теряет, а подбор `pending` при старте — обычный проход воркера, а не отдельный код. Классификация исхода общая с пересборкой журнала. - Исход разбора начал отражать доставку, а не обстоятельства: отмена и занятость базы статус не меняют (иначе конкуренция за базу выводила бы доставку из очереди навсегда), паника свёртки больше не валит процесс, а учёт доставки идёт через транзакцию с повторами. - Длинный бюджет ответа выдан маршруту приёма, а не всему серверу: `write_timeout` в Go покрывает и чтение тела, и общий подъём снял бы защиту с остальных маршрутов.
This commit is contained in:
@@ -3,6 +3,7 @@ package httpapi_test
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
@@ -10,9 +11,9 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.vakhrushev.me/av/healthlog/internal/archive"
|
||||
"git.vakhrushev.me/av/healthlog/internal/fold"
|
||||
"git.vakhrushev.me/av/healthlog/internal/httpapi"
|
||||
"git.vakhrushev.me/av/healthlog/internal/ingest"
|
||||
"git.vakhrushev.me/av/healthlog/internal/store"
|
||||
@@ -259,6 +260,28 @@ func TestHealthz(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Транспорт, не умеющий дедлайнов, приём не роняет: цена отказа здесь наивысшая
|
||||
// в проекте — доставка, не попавшая в архив, не попадает и в журнал.
|
||||
func TestПриёмРаботаетНаТранспортеБезДедлайнов(t *testing.T) {
|
||||
h, st := newAPI(t, nil)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/ingest",
|
||||
strings.NewReader(`{"data":{"metrics":[]}}`))
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("статус = %d, ожидался 200", rec.Code)
|
||||
}
|
||||
n, err := st.CountDeliveries(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("CountDeliveries: %v", err)
|
||||
}
|
||||
if n != 1 {
|
||||
t.Errorf("доставок в учёте %d, ожидалась 1", n)
|
||||
}
|
||||
}
|
||||
|
||||
func newAPI(t *testing.T, writeTokens []string) (http.Handler, *store.Store) {
|
||||
t.Helper()
|
||||
dir := t.TempDir()
|
||||
@@ -276,10 +299,13 @@ func newAPI(t *testing.T, writeTokens []string) (http.Handler, *store.Store) {
|
||||
|
||||
log := slog.New(slog.DiscardHandler)
|
||||
h := httpapi.New(httpapi.Options{
|
||||
Ingest: ingest.New(arch, st, fold.New(arch, st, 0, log), log),
|
||||
Ingest: ingest.New(arch, st, nil, log),
|
||||
Log: log,
|
||||
WriteTokens: writeTokens,
|
||||
MaxBodyMB: 1,
|
||||
// Бюджет задаётся всегда: httptest.ResponseRecorder дедлайнов не умеет,
|
||||
// и это ровно тот транспорт, на котором приём обязан продолжать работать.
|
||||
IngestWriteBudget: time.Minute,
|
||||
})
|
||||
return h, st
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user