check / check (push) Waiting to run
Each database target on the webhook page has a Download button that streams its archive as gzipped JSON, archive-WEBHOOKNAME-TARGETNAME-TIME.json.gz, with names made safe by delivery.ArchiveFileName's function. The export reads one consistent snapshot through one cursor in a read-only transaction, so archive writes carry on, and holds the rename lock only while it reads the stored names and opens the file. It extends its write deadline as it writes, so a large archive downloads for as long as the client reads; a failure after the response has started aborts the connection so the browser marks the download failed. The request limit is now the service's own middleware, which no longer writes a 504 over a response already started. Model: opus-5-5
57 lines
1.3 KiB
Go
57 lines
1.3 KiB
Go
package middleware_test
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestTimeout proves the request limit answers 504 to a handler that
|
|
// outlasts it without starting its response, and leaves a response the
|
|
// handler has started with the status it sent. Both are what the
|
|
// access log records.
|
|
func TestTimeout(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
const limit = 10 * time.Millisecond
|
|
|
|
for _, tc := range []struct {
|
|
name string
|
|
sent int // the status the handler sends, or 0 for none
|
|
want int
|
|
}{
|
|
{name: "not started", sent: 0, want: http.StatusGatewayTimeout},
|
|
{name: "started", sent: http.StatusOK, want: http.StatusOK},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m, buf := capturingMiddleware(t)
|
|
handler := m.Logging()(m.Timeout(limit)(http.HandlerFunc(
|
|
func(w http.ResponseWriter, r *http.Request) {
|
|
if tc.sent != 0 {
|
|
w.WriteHeader(tc.sent)
|
|
}
|
|
|
|
<-r.Context().Done()
|
|
},
|
|
)))
|
|
|
|
w := httptest.NewRecorder()
|
|
handler.ServeHTTP(w, httptest.NewRequestWithContext(
|
|
t.Context(), http.MethodGet, "/", nil,
|
|
))
|
|
|
|
assert.Equal(t, tc.want, w.Code)
|
|
|
|
entries := accessLogEntries(t, buf)
|
|
require.Len(t, entries, 1)
|
|
assert.EqualValues(t, tc.want, entries[0]["status"])
|
|
})
|
|
}
|
|
}
|