[SDTEST-2993] Switch to paginated endpoint for retrieving known tests#8380
Conversation
The known tests endpoint now returns results page by page instead of in
a single bulk response. This reduces load on the backend storage layer
and avoids timeouts for repositories with large numbers of tests.
The client sends page_info:{} on the first request to signal pagination
support, then follows cursor-based pagination until has_next is false.
Results are merged locally across all pages. A 10,000-page safety valve
prevents runaway loops. Backward compatible with non-paginated responses.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Change KnownTestsSuites value type from string[] to List<string> and use AddRange instead of allocating new arrays for merging - Extract pageResponse.Value and pageInfo.Value.Cursor to local vars - Use StringUtil.IsNullOrEmpty instead of string.IsNullOrEmpty - Rename TestsJsonPages to KnownTestsJsonPages in MockData - Return collected data instead of default when hitting max pages limit Co-Authored-By: Claude Opus 4.6 <[email protected]>
BenchmarksBenchmark execution time: 2026-04-15 18:27:12 Comparing candidate commit b7901c5 in PR branch Found 1 performance improvements and 1 performance regressions! Performance is the same for 25 metrics, 0 unstable metrics, 87 known flaky benchmarks.
|
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (8380) and master. ✅ No regressions detected - check the details below Full Metrics ComparisonFakeDbCommand
HttpMessageHandler
Comparison explanationExecution-time benchmarks measure the whole time it takes to execute a program, and are intended to measure the one-off costs. Cases where the execution time results for the PR are worse than latest master results are highlighted in **red**. The following thresholds were used for comparing the execution times:
Note that these results are based on a single point-in-time result for each branch. For full results, see the dashboard. Graphs show the p99 interval based on the mean and StdDev of the test run, as well as the mean value of the run (shown as a diamond below the graph). Duration chartsFakeDbCommand (.NET Framework 4.8)gantt
title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8380) - mean (72ms) : 69, 75
master - mean (72ms) : 70, 75
section Bailout
This PR (8380) - mean (76ms) : 74, 79
master - mean (76ms) : 74, 78
section CallTarget+Inlining+NGEN
This PR (8380) - mean (1,063ms) : 1022, 1104
master - mean (1,066ms) : 1018, 1115
FakeDbCommand (.NET Core 3.1)gantt
title Execution time (ms) FakeDbCommand (.NET Core 3.1)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8380) - mean (112ms) : 108, 116
master - mean (114ms) : 110, 117
section Bailout
This PR (8380) - mean (113ms) : 110, 116
master - mean (115ms) : 112, 118
section CallTarget+Inlining+NGEN
This PR (8380) - mean (787ms) : 768, 807
master - mean (786ms) : 767, 806
FakeDbCommand (.NET 6)gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8380) - mean (100ms) : 97, 103
master - mean (100ms) : 97, 102
section Bailout
This PR (8380) - mean (101ms) : 98, 103
master - mean (99ms) : 97, 101
section CallTarget+Inlining+NGEN
This PR (8380) - mean (935ms) : 897, 973
master - mean (931ms) : 901, 962
FakeDbCommand (.NET 8)gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8380) - mean (98ms) : 94, 103
master - mean (99ms) : 95, 102
section Bailout
This PR (8380) - mean (100ms) : 98, 103
master - mean (99ms) : 97, 102
section CallTarget+Inlining+NGEN
This PR (8380) - mean (818ms) : 779, 857
master - mean (815ms) : 780, 849
HttpMessageHandler (.NET Framework 4.8)gantt
title Execution time (ms) HttpMessageHandler (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8380) - mean (211ms) : 207, 215
master - mean (212ms) : 206, 218
section Bailout
This PR (8380) - mean (215ms) : 210, 219
master - mean (215ms) : 211, 219
section CallTarget+Inlining+NGEN
This PR (8380) - mean (1,228ms) : 1174, 1281
master - mean (1,231ms) : 1180, 1281
HttpMessageHandler (.NET Core 3.1)gantt
title Execution time (ms) HttpMessageHandler (.NET Core 3.1)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8380) - mean (306ms) : 298, 314
master - mean (306ms) : 299, 314
section Bailout
This PR (8380) - mean (306ms) : 300, 312
master - mean (305ms) : 297, 313
section CallTarget+Inlining+NGEN
This PR (8380) - mean (1,021ms) : 995, 1046
master - mean (1,018ms) : 990, 1047
HttpMessageHandler (.NET 6)gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8380) - mean (298ms) : 289, 307
master - mean (299ms) : 292, 306
section Bailout
This PR (8380) - mean (297ms) : 290, 305
master - mean (299ms) : 293, 304
section CallTarget+Inlining+NGEN
This PR (8380) - mean (1,183ms) : 1151, 1214
master - mean (1,182ms) : 1152, 1213
HttpMessageHandler (.NET 8)gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8380) - mean (298ms) : 293, 304
master - mean (297ms) : 292, 303
section Bailout
This PR (8380) - mean (299ms) : 293, 304
master - mean (298ms) : 292, 303
section CallTarget+Inlining+NGEN
This PR (8380) - mean (1,096ms) : 988, 1204
master - mean (1,080ms) : 983, 1177
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MergeKnownTests returned early without initializing the aggregate dictionary when a page had Count: 0. This left aggregate as null, causing KnownTestsFeature.Enabled to return false and preventing EFD from activating. Co-Authored-By: Claude Opus 4.6 <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0792d15b95
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
andrewlock
left a comment
There was a problem hiding this comment.
I think the error-path handling may need some more explicit handling one way or another + potentially some testing... There's currently a single happy-path integration test, maybe we should have tests for when the response isn't what we expect etc? Otherwise just minor things, mostly not for addressing in this PR I think
| if (!aggregate.TryGetValue(moduleEntry.Key, out var existingSuites) || existingSuites is null) | ||
| { | ||
| existingSuites = new KnownTestsResponse.KnownTestsSuites(); | ||
| aggregate[moduleEntry.Key] = existingSuites; |
There was a problem hiding this comment.
this seems to be the point you need to create the aggregate if you haven't already?
andrewlock
left a comment
There was a problem hiding this comment.
Oops, meant to approve with the above comments
78d84c3 to
3423bb3
Compare
Summary
api/v2/ci/libraries/tests) as part of SDTEST-2993page_infoin requests and followshas_next/cursorpagination, deep-merging test results across all pagespage_infoare treated as single-page (existing behavior)Changes
tracer/src/Datadog.Trace/Ci/Net/TestOptimizationClient.GetKnownTestsAsync.cs— Core pagination loop withMergeKnownTests(), newPageInfoRequest/PageInfoResponse/KnownTestsPageResponseDTOstracer/test/.../CI/TestingFrameworkEvpTest.cs— Mock server supports paginated response mode viaTestsJsonPagesarraytracer/test/.../CI/XUnitEvpTests.cs— Newefd_with_test_bypass_paginatedtest scenariotracer/test/snapshots/XUnitEvpTests.EarlyFlakeDetection_efd_with_test_bypass_paginated.verified.txt— Snapshot for paginated scenarioTest plan
🤖 Generated with Claude Code