Repository navigation
Execution list single query - #96
Merged
alexanderoster merged 3 commits intoNov 5, 2026
Merged
Conversation
krixkrix
force-pushed
the
execution-list-single-query
branch
from
November 4, 2026 09:04
cf97158 to
db44520
Compare
DevTools/executionlist_perf seeds N build jobs and executions into a scratch MinimalSystem server and measures GET /api/executions: the full list, concurrent loads, ?since= deltas and the /api/frontend snapshot, with latency, response size and amc_server CPU. It gives repeatable before/after numbers for the following execution list changes. Standard library Python only.
Every BuildJobExecution getter used by an execution list (status, description, end time stamp, elapsed time, and the job's thumbnail via RetrieveJob) runs its own query, so a list of N executions costs about 6N queries. The execution SELECT now also loads these values, and new getters return them without querying again: GetLoadedStatus, GetLoadedStatusString, GetLoadedDescription, GetLoadedEndTimeStampInMicroseconds, ComputeLoadedElapsedTimeInMicroseconds, JobHasThumbnailStream and GetJobThumbnailStreamUUID. The existing getters still read fresh, because long-lived plugin objects rely on that. The SELECT was copied into five queries that had to match the column order by hand. It now lives in CBuildJobExecution::selectQueryWithoutConditions(). A damaged job row (missing, unparseable status, malformed thumbnail UUID) used to make the whole list and every ?since= delta throw. It is now reported as job status Deleted or as no thumbnail, for its own entry only. Unit tests: LibMCData_BuildJobs/ListExecs*.
/api/executions wrote each entry with fresh getters (GetStatus, GetStatusString, GetDescription, GetEndTimeStamp, ComputeElapsedTime) and a RetrieveJob for the thumbnail: about six queries per execution, for the full list and for every ?since= delta. Each entry is now written by writeExecutionListEntryToJSON from the values the list query already loaded, so a list request is one query whatever its length. The JSON is unchanged, and an execution whose job row is missing no longer fails the request. At 2000 executions (DevTools/executionlist_perf, debug build) one full list drops from 1.2 s to 63 ms, six concurrent loads from 8.3 s to 0.18 s, and a 100-row delta from 65 ms to 5 ms. The response bodies are byte-identical before and after. Unit test: LibMCData_BuildJobs/ListExecsJSONEntry.
krixkrix
force-pushed
the
execution-list-single-query
branch
from
November 5, 2026 15:45
db44520 to
162b893
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GET /api/executions(the Build History list, full and?since=deltas) ran about six SQL queries per execution. It now runs one query per request, whatever the list length.GetLoadedStatus,GetLoadedStatusString,GetLoadedDescription,GetLoadedEndTimeStampInMicroseconds,ComputeLoadedElapsedTimeInMicroseconds,JobHasThumbnailStreamandGetJobThumbnailStreamUUID. The existing getters still read fresh from the database, so plugins see no change.CBuildJobExecution::selectQueryWithoutConditions().DevTools/executionlist_perf/seeds N executions into a scratch MinimalSystem server and measures the list, so the numbers below can be reproduced.Evidence
executionlist_perf.py run -n <N>, same seeded database before and after,-O0dev build, median of 5:?since=delta, 2000 executions--damaged 1)amc_serverbusy for seconds.After: the
/api/executionsresponse bodies (full,since=0,since=head-10,since=head) are byte-identical to before.LibMCData_BuildJobsall pass, as does the rest ofamc_unittest(487 of 487):ListExecsLoadedValues: every execution query loads the right values.ListExecsLoadedIsSnapshot: the loaded getters keep the listed values, while the fresh getters re-read the database.ListExecsMalformedJobRowandListExecsOrphanedExecution: a damaged row degrades only its own entry.ListExecsJSONEntry: the entry JSON written from the loaded values.Merge Danger
Door: two-way
The ACT changes only add methods. There is no schema migration, and the JSON format is unchanged.
Blast Radius: small
It touches every place that builds execution objects:
ListJobExecutions,ListJobExecutionsChangedSince,RetrieveJobExecutionandRetrieveBuildJobExecutions[ByStatus]. A bug in the shared SELECT would therefore show up in all of them. The unit tests cover each of those paths. Plugins that hold long-lived execution objects keep the fresh-reading getters.