diff --git a/internal/client/client_test.go b/internal/client/client_test.go index 5a18fe6..1a0c1fa 100644 --- a/internal/client/client_test.go +++ b/internal/client/client_test.go @@ -255,10 +255,12 @@ func fakeIperf3(t *testing.T) string { t.Helper() path := filepath.Join(t.TempDir(), "iperf3") script := `#!/bin/sh -if echo "$@" | grep -q -- "-s"; then - sleep 10 - exit 0 -fi +for arg in "$@"; do + if [ "$arg" = "-s" ]; then + sleep 10 + exit 0 + fi +done cat <<'JSON' {"end":{"sum_sent":{"bytes":1048576,"bits_per_second":88000000},"sum_received":{"bytes":1048576,"bits_per_second":87000000}}} JSON diff --git a/internal/store/store.go b/internal/store/store.go index 6ecd8e7..7ef2b73 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -20,6 +20,8 @@ type Store struct { mu sync.Mutex } +const maxRecordLineBytes = 64 * 1024 * 1024 + type ClientInfo struct { IP string `json:"ip"` ISP string `json:"isp,omitempty"` @@ -89,6 +91,7 @@ func (s *Store) List(ctx context.Context, limit int) ([]Record, error) { var records []Record scanner := bufio.NewScanner(file) + scanner.Buffer(make([]byte, 64*1024), maxRecordLineBytes) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if line == "" { diff --git a/internal/store/store_test.go b/internal/store/store_test.go index e8ea92a..12de02c 100644 --- a/internal/store/store_test.go +++ b/internal/store/store_test.go @@ -121,3 +121,41 @@ func TestStoreListIgnoresBlankLinesAndMissingFile(t *testing.T) { t.Fatalf("records order = %s, %s; want run-2, run-1", records[0].ID, records[1].ID) } } + +func TestStoreListsLargeRecordsWithFullSampleCurves(t *testing.T) { + path := filepath.Join(t.TempDir(), "records.jsonl") + store := New(path) + ctx := context.Background() + + var samples []probe.Sample + for i := 0; i < 2000; i++ { + samples = append(samples, probe.Sample{ + At: time.Date(2026, 6, 10, 8, 0, 0, 0, time.UTC).Add(time.Duration(i) * time.Millisecond), + Kind: "download", + Success: true, + LatencyMS: 10.5, + Bytes: 4 * 1024 * 1024, + Mbps: 38.25, + }) + } + + if err := store.Append(ctx, Record{ + ID: "large-run", + Samples: samples, + Summary: probe.Summary{ + ID: "large-run", + Target: "example.com:443", + Samples: len(samples), + }, + }); err != nil { + t.Fatalf("Append large record: %v", err) + } + + records, err := store.List(ctx, 10) + if err != nil { + t.Fatalf("List returned error: %v", err) + } + if len(records) != 1 || records[0].ID != "large-run" || len(records[0].Samples) != len(samples) { + t.Fatalf("records = %#v, want large record with %d samples", records, len(samples)) + } +} diff --git a/internal/web/server_test.go b/internal/web/server_test.go index 8603544..b397bff 100644 --- a/internal/web/server_test.go +++ b/internal/web/server_test.go @@ -1028,10 +1028,12 @@ func fakeIperf3(t *testing.T) string { t.Helper() path := filepath.Join(t.TempDir(), "iperf3") script := `#!/bin/sh -if echo "$@" | grep -q -- "-s"; then - sleep 10 - exit 0 -fi +for arg in "$@"; do + if [ "$arg" = "-s" ]; then + sleep 10 + exit 0 + fi +done cat <<'JSON' {"end":{"sum_sent":{"bytes":1048576,"bits_per_second":88000000},"sum_received":{"bytes":1048576,"bits_per_second":87000000}}} JSON