TRT-2734: add release_definitions table and loader#3679
Conversation
|
Pipeline controller notification For optional jobs, comment This repository is configured in: automatic mode |
|
Skipping CI for Draft Pull Request. |
eccf470 to
c3dca6d
Compare
c3dca6d to
23f283f
Compare
|
Scheduling required tests: |
| func (s *Server) getReleases(ctx context.Context, forceRefresh ...bool) ([]sippyv1.Release, error) { | ||
| if s.bigQueryClient != nil { | ||
| refresh := len(forceRefresh) > 0 && forceRefresh[0] | ||
| return api.GetReleases(ctx, s.bigQueryClient, refresh) | ||
| // getReleases returns release data from PostgreSQL. | ||
| func (s *Server) getReleases(ctx context.Context) ([]sippyv1.Release, error) { | ||
| if s.db != nil { | ||
| releases, err := api.GetReleasesFromDB(ctx, s.db) |
There was a problem hiding this comment.
this removes the cache. reading from a small postgres table is fast, but not nearly as fast as reading from redis, and this page gets called.... a lot. with React calling it several times per UI transition it may even be noticeable at a human timescale. consider whether we don't want caching here?
There was a problem hiding this comment.
Good call raising this. I traced all the callers to understand the full impact.
getReleases() is called by 8 HTTP handlers:
- /api/releases (page load, ~15 calls/hour)
- /api/component_readiness (every CR request)
- /api/component_readiness/test_details
- /api/component_readiness/views
- 4 triage/regression endpoints
The old Redis cache (8h TTL, key "Releases~") was valuable because it avoided a BigQuery round-trip on every one of these requests. That saved both latency and BQ query cost.
With PostgreSQL, the query is ~7ms for ~20 rows. The CR endpoints themselves take seconds, so 7ms is noise. There's no per-query cost like BQ.
More importantly, these callers are transitional. The CR handlers use release data for two things: resolving relative time strings like "ga-30d" into absolute dates, and generating HATEOAS links with correct time parameters. As we move CR fully to PostgreSQL:
- The CR test status queries will use pre-aggregated matviews per release (e.g., cr_base_agg_4.21), where the GA-based time window is baked into the matview at build time. No release metadata lookup needed at request time.
- For any queries that still need release dates, the lookup can fold into the main query as a JOIN against release_definitions rather than a separate round-trip.
That leaves /api/releases as the only endpoint that needs a standalone query, at ~15 calls/hour. Adding a Redis cache layer for that adds complexity with no user-visible benefit. The HTTP round-trip overhead alone (~50-200ms) dwarfs the 7ms PG query.
If we see this become a bottleneck in practice, we can add caching for PQ later, but I don't think it's warranted now.
09c13a6 to
4592ca7
Compare
|
Scheduling required tests: |
|
@mstaeble: This pull request references TRT-2734 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set. DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository. |
|
Tip For best results, initiate chat on the files or code changes. This comment is an automated notice from |
Cherry-pick from PR openshift#3716 with conflict resolution: - Use civil.Date for date-only fields (GA dates, development start dates) - Use TIMESTAMP WITH TIME ZONE and DATE types in PostgreSQL - RFC 3339 for API timestamps, YYYY-MM-DD for dates - Resolve conflict in postgres provider (keep GetReleasesFromDB from PR openshift#3679) - Add time.Time to civil.Date conversion in DefinitionToRelease Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| releases = append(releases, rel) | ||
| } | ||
| return releases, nil | ||
| return api.GetReleasesFromDB(ctx, p.dbc) |
There was a problem hiding this comment.
Do we have a race condition when this merges prior to load running? Should this be a two-stage process where we init / load the new table then switch over, or is that happening externally?
There was a problem hiding this comment.
Good point. I've split this into two PRs to avoid the race condition:
- TRT-2734: add release_definitions table and loader #3679 (this PR): Creates the release_definitions table, adds the release-definitions loader, and seeds data for local dev. No consumers are switched — the existing getReleases() and QueryReleases() paths continue to use BigQuery / hardcoded metadata. This is purely additive and safe to merge immediately.
- [WIP] TRT-2734: switch release consumers from BigQuery to PostgreSQL #3736: Switches getReleases() and the PG provider to read from release_definitions instead of BigQuery / the hardcoded map. This should only merge after TRT-2734: add release_definitions table and loader #3679 has been deployed and at least one load cycle has populated the table.
9283507 to
39eb557
Compare
|
@mstaeble: No Jira issue is referenced in the title of this pull request. DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository. |
|
Tip For best results, initiate chat on the files or code changes.
|
|
Scheduling required tests: |
|
@mstaeble: This pull request references TRT-2734 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set. DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository. |
|
Tip For best results, initiate chat on the files or code changes.
|
| // loader will populate it for subsequent runs. | ||
| releaseConfigs := []sippyv1.Release{} | ||
| if dbErr == nil { | ||
| releaseConfigs, _ = api.GetReleasesFromDB(context.Background(), dbc) |
There was a problem hiding this comment.
I think we still have an issue here. The releases are needed for partitioning and the loader. You could look to have GetReleasesFromDB fallback to GetReleasesFromBigQuery when results are empty or keep the BQ call here for now until we know it is populated.
There was a problem hiding this comment.
Good point. I've added a BQ fallback in load.go. It reads from PG first, and falls back to GetReleasesFromBigQuery when the table is empty (e.g., first run on a new database). This ensures partitioning and downstream loaders work correctly even before the release-definitions loader has populated the table.
There was a problem hiding this comment.
One last consideration, previously we returned if there was an error loading the releases. You are now logging the errors in the api calls but drop the errors here. I don't think we expect the loader to work without releases, at least not the job loader.
I don't want to overengineer this but should we validate we have at least 1 release and if not then exit?
There was a problem hiding this comment.
Updated. Error handling now matches the original behavior: hard exit on query error (return errors.Wrapf(err, ...)), silent continue on empty results. It tries PG first, falls back to BQ if PG returns no rows (e.g., first run).
39eb557 to
790c4d8
Compare
|
Scheduling required tests: |
790c4d8 to
94669d7
Compare
Create a release_definitions table to store release metadata (GA dates, development start dates, previous release, capabilities, product, status) synced from BigQuery. This is the first phase of moving release metadata from BigQuery to PostgreSQL. Key changes: - Add ReleaseDefinition model with capability constants and HasCapability method - Add release-definitions loader (--loader release-definitions) that fetches from BQ and syncs to PG via upsert - Add GetReleasesFromDB and DefinitionToRelease for reading from PG - Add GetReleaseRowsFromBigQuery for direct BQ row access - Seed data populates release_definitions for local development - Load command reads release configs from PG with BQ fallback for first run when the table is empty No consumers are switched in this phase. The existing getReleases() and QueryReleases() paths continue to use BigQuery / hardcoded metadata. A follow-up PR will switch consumers to read from the new table once it has been populated by the load cycle. Ref: TRT-2734 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
94669d7 to
5d8e3c2
Compare
|
/lgtm |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: mstaeble, neisw The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
Scheduling required tests: |
|
@mstaeble: all tests passed! Full PR test history. Your PR dashboard. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here. |
Cherry-pick from PR openshift#3716 with conflict resolution: - Use civil.Date for date-only fields (GA dates, development start dates) - Use TIMESTAMP WITH TIME ZONE and DATE types in PostgreSQL - RFC 3339 for API timestamps, YYYY-MM-DD for dates - Resolve conflict in postgres provider (keep GetReleasesFromDB from PR openshift#3679) - Add time.Time to civil.Date conversion in DefinitionToRelease Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Creates a
release_definitionstable in PostgreSQL and a loader to populate it from BigQuery. This is the first phase of moving release metadata from BigQuery to PostgreSQL (TRT-2734).No consumers are switched in this PR. The existing
getReleases()andQueryReleases()paths continue to use BigQuery / hardcoded metadata. A follow-up PR (#3736) will switch consumers to read from the new table once it has been populated by the load cycle.ReleaseDefinitionmodel with capability constants andHasCapabilitymethodrelease-definitionsloader (--loader release-definitions) that fetches from BQ and syncs to PG via upsertGetReleasesFromDBandDefinitionToReleasefor reading from PGGetReleaseRowsFromBigQueryfor direct BQ row accessrelease_definitionsfor local developmentTest plan
go build ./...passesgo vet ./...passesmake lintpassesgo test ./pkg/... ./cmd/...passessippy servewith seed data works correctly (no behavior change)Staging verification
Deployed and ran the loader as a one-off job:
Synced 36 release definitions from BigQuery to staging PostgreSQL (all OCP releases 3.11 through 5.0, OKD, ROSA, ARO, HyperShift, and CAPI entries).
Ref: TRT-2734
@coderabbitai ignore
🤖 Generated with Claude Code