aboutsummaryrefslogtreecommitdiff
path: root/internal/ingest/client_retry_test.go
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-26 15:07:03 -0800
committerFuwn <[email protected]>2026-02-26 15:07:03 -0800
commitf1b26a68534e4299de7b5fe6b15d2b248fac40e1 (patch)
tree4003d041bc46866b7d4b7f0bfb6c6924d991cbb6 /internal/ingest/client_retry_test.go
parentfeat: initial Plutia release — verifiable high-performance PLC mirror (mirr... (diff)
downloadplutia-test-f1b26a68534e4299de7b5fe6b15d2b248fac40e1.tar.xz
plutia-test-f1b26a68534e4299de7b5fe6b15d2b248fac40e1.zip
feat: harden launch readiness with versioning, metrics, and resilience
Diffstat (limited to 'internal/ingest/client_retry_test.go')
-rw-r--r--internal/ingest/client_retry_test.go63
1 files changed, 63 insertions, 0 deletions
diff --git a/internal/ingest/client_retry_test.go b/internal/ingest/client_retry_test.go
new file mode 100644
index 0000000..a23fceb
--- /dev/null
+++ b/internal/ingest/client_retry_test.go
@@ -0,0 +1,63 @@
+package ingest
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "sync/atomic"
+ "testing"
+ "time"
+)
+
+func TestFetchExportLimitedRetries429ThenSucceeds(t *testing.T) {
+ var attempts atomic.Int32
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ n := attempts.Add(1)
+ if n <= 2 {
+ w.Header().Set("Retry-After", "0")
+ http.Error(w, "rate limited", http.StatusTooManyRequests)
+ return
+ }
+ _, _ = fmt.Fprintln(w, `{"seq":1,"did":"did:plc:alice","cid":"cid1","operation":{"x":1}}`)
+ }))
+ defer ts.Close()
+
+ client := NewClient(ts.URL, ClientOptions{
+ MaxAttempts: 5,
+ BaseDelay: time.Millisecond,
+ MaxDelay: 2 * time.Millisecond,
+ })
+ records, err := client.FetchExportLimited(context.Background(), 0, 0)
+ if err != nil {
+ t.Fatalf("fetch export: %v", err)
+ }
+ if len(records) != 1 {
+ t.Fatalf("record count mismatch: got %d want 1", len(records))
+ }
+ if got := attempts.Load(); got != 3 {
+ t.Fatalf("attempt count mismatch: got %d want 3", got)
+ }
+}
+
+func TestFetchExportLimitedDoesNotRetry400(t *testing.T) {
+ var attempts atomic.Int32
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ attempts.Add(1)
+ http.Error(w, "bad request", http.StatusBadRequest)
+ }))
+ defer ts.Close()
+
+ client := NewClient(ts.URL, ClientOptions{
+ MaxAttempts: 5,
+ BaseDelay: time.Millisecond,
+ MaxDelay: 2 * time.Millisecond,
+ })
+ _, err := client.FetchExportLimited(context.Background(), 0, 0)
+ if err == nil {
+ t.Fatalf("expected error for 400 response")
+ }
+ if got := attempts.Load(); got != 1 {
+ t.Fatalf("unexpected retries on 400: got attempts=%d want 1", got)
+ }
+}