Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions pkg/db/query/feature_gates.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,26 @@ import (
)

func GetFeatureGatesFromDB(dbc *gorm.DB, release string, filterOpts *filter.FilterOptions) ([]api.FeatureGate, error) {
// Get tests by feature gate
// Get tests by feature gate.
// Install related FG is special and is covered by install should succeed case.
// Pre-filter with LIKE to avoid running expensive regex on every row.
subQuery := dbc.Table("prow_test_report_7d_matview").
Select(`name, release, regexp_matches(name, '\[(FeatureGate|OCPFeatureGate):([^\]]+)\]|install should succeed') AS match`).
Where("release = ?", release)
Where("release = ?", release).
Where("name LIKE '%FeatureGate:%' OR name LIKE '%install should succeed%'")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regexp match is expensive, but LIKE can use index so its much faster, 4x faster


// Figure out the first release we ever saw a FG
firstSeenQuery := dbc.Table("feature_gates").
Select(`
// Figure out the first release we ever saw a FG.
// Use DISTINCT ON to return exactly one row per feature gate (the earliest release).
firstSeenQuery := dbc.Raw(`
SELECT DISTINCT ON (feature_gate)
feature_gate,
MIN(release) OVER (
PARTITION BY feature_gate
ORDER BY string_to_array(release, '.')::int[] ASC
) AS first_seen_in,
CAST((string_to_array(MIN(release) OVER (PARTITION BY feature_gate), '.'))[1] AS INT) AS first_seen_in_major,
CAST((string_to_array(MIN(release) OVER (PARTITION BY feature_gate), '.'))[2] AS INT) AS first_seen_in_minor
`).
Where("status = 'enabled'")
release AS first_seen_in,
CAST((string_to_array(release, '.'))[1] AS INT) AS first_seen_in_major,
CAST((string_to_array(release, '.'))[2] AS INT) AS first_seen_in_minor
FROM feature_gates
WHERE status = 'enabled'
ORDER BY feature_gate, string_to_array(release, '.')::int[] ASC
`)

query := dbc.Table("feature_gates AS fg").
Select(`
Expand Down
1 change: 1 addition & 0 deletions pkg/sippyserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2740,6 +2740,7 @@ func (s *Server) Serve() {
EndpointPath: "/api/feature_gates",
Description: "Reports feature gates and their test counts for a particular release",
Capabilities: []string{LocalDBCapability},
CacheTime: 4 * time.Hour,
HandlerFunc: s.jsonFeatureGates,
},
{
Expand Down
96 changes: 46 additions & 50 deletions sippy-ng/src/tests/FeatureGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ export default function FeatureGates(props) {
}

const fetchData = () => {
setLoaded(false)
setRows([])

let queryString = ''
if (filterModel && filterModel.items.length > 0) {
queryString +=
Expand Down Expand Up @@ -315,10 +318,6 @@ export default function FeatureGates(props) {
navigate(linkForFGTests(params))
}

useEffect(() => {
setLoaded(false)
}, [filterModel])

useEffect(() => {
fetchData()
document.title = `Sippy > ${props.release} > Feature Gates`
Expand All @@ -340,53 +339,50 @@ export default function FeatureGates(props) {
{fetchError}
</Typography>
)}
{isLoaded ? (
<DataGrid
components={{ Toolbar: GridToolbar }}
rows={rows}
columns={columns}
getRowHeight={() => 'auto'}
autoHeight={true}
rowsPerPageOptions={[10, 25, 50]}
sortModel={[
{
field: sortField,
sort: sort,
},
]}
pageSize={pageSize}
onPageSizeChange={(newPageSize) => setPageSize(newPageSize)}
sortingOrder={['desc', 'asc']}
filterMode="server"
sortingMode="server"
onSortModelChange={(m) => updateSortModel(m)}
sx={{
'& .MuiDataGrid-row:hover': {
cursor: 'pointer', // Change cursor on hover
<DataGrid
loading={!isLoaded}
components={{ Toolbar: GridToolbar }}
rows={rows}
columns={columns}
getRowHeight={() => 'auto'}
autoHeight={true}
rowsPerPageOptions={[10, 25, 50]}
sortModel={[
{
field: sortField,
sort: sort,
},
]}
pageSize={pageSize}
onPageSizeChange={(newPageSize) => setPageSize(newPageSize)}
sortingOrder={['desc', 'asc']}
filterMode="server"
sortingMode="server"
onSortModelChange={(m) => updateSortModel(m)}
sx={{
'& .MuiDataGrid-row:hover': {
cursor: 'pointer',
},
}}
disableSelectionOnClick
filterModel={filterModel}
onRowClick={onRowClick}
componentsProps={{
toolbar: {
bookmarks: bookmarks,
columns: columns,
clearSearch: () => requestSearch(''),
doSearch: requestSearch,
addFilters: (m) => addFilters(m),
filterModel: filterModel,
setFilterModel: setFilterModel,
downloadDataFunc: () => {
return rows
},
}}
disableSelectionOnClick
filterModel={filterModel}
onRowClick={onRowClick}
componentsProps={{
toolbar: {
bookmarks: bookmarks,
columns: columns,
clearSearch: () => requestSearch(''),
doSearch: requestSearch,
addFilters: (m) => addFilters(m),
filterModel: filterModel,
setFilterModel: setFilterModel,
downloadDataFunc: () => {
return rows
},
downloadFilePrefix: 'feature-gates',
},
}}
/>
) : (
<Typography align="center">Loading...</Typography>
)}
downloadFilePrefix: 'feature-gates',
},
}}
/>
</Container>
</Fragment>
)
Expand Down