Add Subscription fields to Alerts table. Modifies Save interface to have a subscription key argument, where one can specify a Subscription. CL also creates granular, isolated tests for each Alert method. Bug: chromium:327485601 Change-Id: I6a5962aa20420f9cccb917316127b59f6cb16a39 Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/844556 Reviewed-by: Ashwin Verleker <ashwinpv@google.com> Commit-Queue: Eduardo Yap <eduardoyap@google.com>
diff --git a/perf/go/alerts/alertstest/BUILD.bazel b/perf/go/alerts/alertstest/BUILD.bazel deleted file mode 100644 index 289a438..0000000 --- a/perf/go/alerts/alertstest/BUILD.bazel +++ /dev/null
@@ -1,13 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "alertstest", - srcs = ["alertstest.go"], - importpath = "go.skia.org/infra/perf/go/alerts/alertstest", - visibility = ["//visibility:public"], - deps = [ - "//perf/go/alerts", - "@com_github_stretchr_testify//assert", - "@com_github_stretchr_testify//require", - ], -)
diff --git a/perf/go/alerts/alertstest/alertstest.go b/perf/go/alerts/alertstest/alertstest.go deleted file mode 100644 index f200f47..0000000 --- a/perf/go/alerts/alertstest/alertstest.go +++ /dev/null
@@ -1,88 +0,0 @@ -// Package alertstest contains test utils for the alerts package. -package alertstest - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.skia.org/infra/perf/go/alerts" -) - -// Store_SaveListDelete tests that an alerts.Store instance operates as expected. -func Store_SaveListDelete(t *testing.T, a alerts.Store) { - ctx := context.Background() - - // TODO(jcgregorio) Break up into finer grained tests. - cfg := alerts.NewConfig() - cfg.Query = "source_type=svg" - cfg.DisplayName = "bar" - err := a.Save(ctx, cfg) - assert.NoError(t, err) - require.NotEqual(t, alerts.BadAlertIDAsAsString, cfg.IDAsString) - - // Confirm it appears in the list. - cfgs, err := a.List(ctx, false) - require.NoError(t, err) - require.Len(t, cfgs, 1) - - // Delete it. - err = a.Delete(ctx, int(cfgs[0].IDAsStringToInt())) - assert.NoError(t, err) - - // Confirm it is still there if we list deleted configs. - cfgs, err = a.List(ctx, true) - assert.NoError(t, err) - assert.Len(t, cfgs, 1) - require.NotEqual(t, alerts.BadAlertIDAsAsString, cfgs[0].IDAsString) - - // Confirm it is not there if we don't list deleted configs. - cfgs, err = a.List(ctx, false) - assert.NoError(t, err) - assert.Len(t, cfgs, 0) - - // Store a second config. - cfg = alerts.NewConfig() - cfg.Query = "source_type=skp" - cfg.DisplayName = "foo" - err = a.Save(ctx, cfg) - assert.NoError(t, err) - - // Confirm they are both listed when including deleted configs, and they are - // ordered by DisplayName. - cfgs, err = a.List(ctx, true) - assert.NoError(t, err) - assert.Len(t, cfgs, 2) - assert.Equal(t, "bar", cfgs[0].DisplayName) - assert.Equal(t, "foo", cfgs[1].DisplayName) -} - -// Store_SaveWithID tests we can save a new Alert with a given ID. -func Store_SaveWithID(t *testing.T, a alerts.Store) { - ctx := context.Background() - - cfg := alerts.NewConfig() - // Add some data to the empty config. - cfg.Query = "source_type=svg" - cfg.DisplayName = "bar" - cfg.IDAsString = "12" - err := a.Save(ctx, cfg) - require.NoError(t, err) - - // Confirm it appears in the list. - cfgs, err := a.List(ctx, false) - require.NoError(t, err) - assert.Len(t, cfgs, 1) - assert.Equal(t, cfg, cfgs[0]) -} - -// SubTestFunction is a func we will call to test one aspect of an -// implementation of regression.Store. -type SubTestFunction func(t *testing.T, store alerts.Store) - -// SubTests are all the subtests we have for regression.Store. -var SubTests = map[string]SubTestFunction{ - "Store_SaveListDelete": Store_SaveListDelete, - "Store_SaveWithID": Store_SaveWithID, -}
diff --git a/perf/go/alerts/configprovider_test.go b/perf/go/alerts/configprovider_test.go index 429bd4e..b4361ba 100644 --- a/perf/go/alerts/configprovider_test.go +++ b/perf/go/alerts/configprovider_test.go
@@ -16,7 +16,7 @@ mutex sync.Mutex } -func (store *MockStore) Save(ctx context.Context, cfg *Alert) error { +func (store *MockStore) Save(ctx context.Context, req *SaveRequest) error { return nil }
diff --git a/perf/go/alerts/mock/Store.go b/perf/go/alerts/mock/Store.go index 34acf6c..5e2ffad 100644 --- a/perf/go/alerts/mock/Store.go +++ b/perf/go/alerts/mock/Store.go
@@ -63,17 +63,17 @@ return r0, r1 } -// Save provides a mock function with given fields: ctx, cfg -func (_m *Store) Save(ctx context.Context, cfg *alerts.Alert) error { - ret := _m.Called(ctx, cfg) +// Save provides a mock function with given fields: ctx, req +func (_m *Store) Save(ctx context.Context, req *alerts.SaveRequest) error { + ret := _m.Called(ctx, req) if len(ret) == 0 { panic("no return value specified for Save") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *alerts.Alert) error); ok { - r0 = rf(ctx, cfg) + if rf, ok := ret.Get(0).(func(context.Context, *alerts.SaveRequest) error); ok { + r0 = rf(ctx, req) } else { r0 = ret.Error(0) }
diff --git a/perf/go/alerts/sqlalertstore/BUILD.bazel b/perf/go/alerts/sqlalertstore/BUILD.bazel index 8251361..4dfe6f1 100644 --- a/perf/go/alerts/sqlalertstore/BUILD.bazel +++ b/perf/go/alerts/sqlalertstore/BUILD.bazel
@@ -28,8 +28,10 @@ # https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes-tests flaky = True, deps = [ - "//perf/go/alerts/alertstest", + "//go/sql/pool", + "//perf/go/alerts", "//perf/go/sql/sqltest", + "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", ], )
diff --git a/perf/go/alerts/sqlalertstore/schema/schema.go b/perf/go/alerts/sqlalertstore/schema/schema.go index c25ab55..276ef9e 100644 --- a/perf/go/alerts/sqlalertstore/schema/schema.go +++ b/perf/go/alerts/sqlalertstore/schema/schema.go
@@ -17,4 +17,10 @@ // Stored as a Unit timestamp. LastModified int `sql:"last_modified INT"` + + // Name of the subscription this alert responds to. + SubscriptionName string `sql:"sub_name STRING"` + + // Revision of the associated subscription. Used to query the Subscriptions table. + SubscriptionRevision string `sql:"sub_revision STRING"` }
diff --git a/perf/go/alerts/sqlalertstore/sqlalertstore.go b/perf/go/alerts/sqlalertstore/sqlalertstore.go index 1c35dcc..add1480 100644 --- a/perf/go/alerts/sqlalertstore/sqlalertstore.go +++ b/perf/go/alerts/sqlalertstore/sqlalertstore.go
@@ -5,6 +5,7 @@ import ( "context" + "database/sql" "encoding/json" "sort" "time" @@ -38,9 +39,9 @@ `, updateAlert: ` UPSERT INTO - Alerts (id, alert, config_state, last_modified) + Alerts (id, alert, config_state, last_modified, sub_name, sub_revision) VALUES - ($1, $2, $3, $4) + ($1, $2, $3, $4, $5, $6) `, deleteAlert: ` UPDATE @@ -84,7 +85,9 @@ } // Save implements the alerts.Store interface. -func (s *SQLAlertStore) Save(ctx context.Context, cfg *alerts.Alert) error { +func (s *SQLAlertStore) Save(ctx context.Context, req *alerts.SaveRequest) error { + + cfg := req.Cfg b, err := json.Marshal(cfg) if err != nil { return skerr.Wrapf(err, "Failed to serialize Alert for saving with ID=%s", cfg.IDAsString) @@ -99,7 +102,16 @@ } cfg.SetIDFromInt64(newID) } else { - if _, err := s.db.Exec(ctx, statements[updateAlert], cfg.IDAsStringToInt(), string(b), cfg.StateToInt(), now); err != nil { + nameOrNull := sql.NullString{Valid: false} + revisionOrNull := sql.NullString{Valid: false} + + if req.SubKey != nil { + nameOrNull.String = req.SubKey.SubName + nameOrNull.Valid = true + revisionOrNull.String = req.SubKey.SubRevision + revisionOrNull.Valid = true + } + if _, err := s.db.Exec(ctx, statements[updateAlert], cfg.IDAsStringToInt(), string(b), cfg.StateToInt(), now, nameOrNull, revisionOrNull); err != nil { return skerr.Wrapf(err, "Failed to update Alert with ID=%s", cfg.IDAsString) } }
diff --git a/perf/go/alerts/sqlalertstore/sqlalertstore_test.go b/perf/go/alerts/sqlalertstore/sqlalertstore_test.go index f769416..6df01de 100644 --- a/perf/go/alerts/sqlalertstore/sqlalertstore_test.go +++ b/perf/go/alerts/sqlalertstore/sqlalertstore_test.go
@@ -1,21 +1,286 @@ package sqlalertstore import ( + "context" + "database/sql" + "encoding/json" "testing" + "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.skia.org/infra/perf/go/alerts/alertstest" + "go.skia.org/infra/go/sql/pool" + "go.skia.org/infra/perf/go/alerts" "go.skia.org/infra/perf/go/sql/sqltest" ) -func TestSQLAlertStore_CockroachDB(t *testing.T) { +func setUp(t *testing.T) (alerts.Store, pool.Pool) { + db := sqltest.NewCockroachDBForTests(t, "alertstore") + store, err := New(db) + require.NoError(t, err) - for name, subTest := range alertstest.SubTests { - t.Run(name, func(t *testing.T) { - db := sqltest.NewCockroachDBForTests(t, "alertstore") - store, err := New(db) - require.NoError(t, err) - subTest(t, store) - }) + return store, db +} + +// Tests a hypothetical pipeline of Store. +func TestStore_SaveListDelete(t *testing.T) { + ctx := context.Background() + store, _ := setUp(t) + + // TODO(jcgregorio) Break up into finer grained tests. + cfg := alerts.NewConfig() + cfg.Query = "source_type=svg" + cfg.DisplayName = "bar" + err := store.Save(ctx, &alerts.SaveRequest{ + Cfg: cfg, + SubKey: nil, + }) + assert.NoError(t, err) + require.NotEqual(t, alerts.BadAlertIDAsAsString, cfg.IDAsString) + + // Confirm it appears in the list. + cfgs, err := store.List(ctx, false) + require.NoError(t, err) + require.Len(t, cfgs, 1) + + // Delete it. + err = store.Delete(ctx, int(cfgs[0].IDAsStringToInt())) + assert.NoError(t, err) + + // Confirm it is still there if we list deleted configs. + cfgs, err = store.List(ctx, true) + assert.NoError(t, err) + assert.Len(t, cfgs, 1) + require.NotEqual(t, alerts.BadAlertIDAsAsString, cfgs[0].IDAsString) + + // Confirm it is not there if we don't list deleted configs. + cfgs, err = store.List(ctx, false) + assert.NoError(t, err) + assert.Len(t, cfgs, 0) + + // Store a second config. + cfg = alerts.NewConfig() + cfg.Query = "source_type=skp" + cfg.DisplayName = "foo" + err = store.Save(ctx, &alerts.SaveRequest{ + Cfg: cfg, + SubKey: nil, + }) + assert.NoError(t, err) + + // Confirm they are both listed when including deleted configs, and they are + // ordered by DisplayName. + cfgs, err = store.List(ctx, true) + assert.NoError(t, err) + assert.Len(t, cfgs, 2) + assert.Equal(t, "bar", cfgs[0].DisplayName) + assert.Equal(t, "foo", cfgs[1].DisplayName) +} + +// Tests we can list two active Alerts. +func TestStoreList_ListActiveAlerts(t *testing.T) { + ctx := context.Background() + store, db := setUp(t) + + cfg1 := alerts.NewConfig() + cfg1.SetIDFromInt64(1) + cfg1.Query = "source_type=svg" + cfg1.DisplayName = "bar" + insertAlertToDb(t, ctx, db, cfg1, nil) + + cfg2 := alerts.NewConfig() + cfg2.SetIDFromInt64(2) + cfg2.Query = "source_type=skp" + cfg2.DisplayName = "foo" + insertAlertToDb(t, ctx, db, cfg2, nil) + + cfgs, err := store.List(ctx, true) + assert.NoError(t, err) + assert.Len(t, cfgs, 2) + assert.Equal(t, "bar", cfgs[0].DisplayName) + assert.Equal(t, "foo", cfgs[1].DisplayName) + assert.Equal(t, "source_type=svg", cfgs[0].Query) + assert.Equal(t, "source_type=skp", cfgs[1].Query) + assert.Equal(t, "1", cfgs[0].IDAsString) + assert.Equal(t, "2", cfgs[1].IDAsString) + + // Confirm all alerts are active. + cfgs2, err := store.List(ctx, false) + assert.Equal(t, cfgs, cfgs2) +} + +// Tests we can list one deleted Alert. +func TestStoreList_ListDeletedAlert(t *testing.T) { + ctx := context.Background() + store, db := setUp(t) + + cfg1 := alerts.NewConfig() + cfg1.SetIDFromInt64(1) + cfg1.Query = "source_type=svg" + cfg1.DisplayName = "bar" + insertAlertToDb(t, ctx, db, cfg1, nil) + + cfg2 := alerts.NewConfig() + cfg2.SetIDFromInt64(2) + cfg2.Query = "source_type=skp" + cfg2.DisplayName = "foo" + cfg2.StateAsString = alerts.DELETED + insertAlertToDb(t, ctx, db, cfg2, nil) + + cfgs, err := store.List(ctx, true) + assert.NoError(t, err) + assert.Len(t, cfgs, 2) + assert.Equal(t, "bar", cfgs[0].DisplayName) + assert.Equal(t, "foo", cfgs[1].DisplayName) + assert.Equal(t, "source_type=svg", cfgs[0].Query) + assert.Equal(t, "source_type=skp", cfgs[1].Query) + assert.Equal(t, "1", cfgs[0].IDAsString) + assert.Equal(t, "2", cfgs[1].IDAsString) + + // Confirm one alert is active + cfgs2, err := store.List(ctx, false) + assert.NotEqual(t, cfgs, cfgs2) + assert.Len(t, cfgs2, 1) + assert.Equal(t, "bar", cfgs2[0].DisplayName) + assert.Equal(t, "source_type=svg", cfgs2[0].Query) + assert.Equal(t, "1", cfgs2[0].IDAsString) +} + +// Tests we can mark one Alert as deleted using Delete +func TestStoreDelete_DeleteOneAlert(t *testing.T) { + ctx := context.Background() + store, db := setUp(t) + + cfg := alerts.NewConfig() + cfg.SetIDFromInt64(2) + cfg.Query = "source_type=svg" + cfg.DisplayName = "bar" + insertAlertToDb(t, ctx, db, cfg, nil) + + _, subKey1, configState1 := getAlertFromDb(t, ctx, db, 2) + assert.Nil(t, subKey1) + assert.Equal(t, alerts.ConfigStateToInt(alerts.ACTIVE), configState1) + + err := store.Delete(ctx, 2) + require.NoError(t, err) + + cfg2, subKey2, configState2 := getAlertFromDb(t, ctx, db, 2) + assert.Nil(t, subKey2) + assert.Equal(t, "bar", cfg2.DisplayName) + assert.Equal(t, "source_type=svg", cfg2.Query) + assert.Equal(t, "2", cfg2.IDAsString) + assert.Equal(t, alerts.ConfigStateToInt(alerts.DELETED), configState2) +} + +// Tests that inserting an ID with -1 ID, generates a new ID for the Alert. +func TestStoreSave_SaveWithBadID(t *testing.T) { + ctx := context.Background() + store, db := setUp(t) + + cfg := alerts.NewConfig() + cfg.SetIDFromInt64(alerts.BadAlertID) + cfg.Query = "source_type=svg" + cfg.DisplayName = "bar" + err := store.Save(ctx, &alerts.SaveRequest{ + Cfg: cfg, + SubKey: nil, + }) + require.NoError(t, err) + + _, subKey1, configState1 := getAlertFromDb(t, ctx, db, cfg.IDAsStringToInt()) + assert.Nil(t, subKey1) + assert.Equal(t, alerts.ConfigStateToInt(alerts.ACTIVE), configState1) + assert.NotEqual(t, alerts.BadAlertID, cfg.IDAsStringToInt()) +} + +// Tests inserting an Alert with valid ID. +func TestStoreSave_SaveWithValidID(t *testing.T) { + ctx := context.Background() + store, db := setUp(t) + + cfg := alerts.NewConfig() + cfg.SetIDFromInt64(1) + cfg.Query = "source_type=svg" + cfg.DisplayName = "bar" + err := store.Save(ctx, &alerts.SaveRequest{ + Cfg: cfg, + SubKey: nil, + }) + require.NoError(t, err) + _, subKey, configState := getAlertFromDb(t, ctx, db, 1) + assert.Nil(t, subKey) + assert.Equal(t, alerts.ConfigStateToInt(alerts.ACTIVE), configState) +} + +// Tests inserting an Alert with an associated Subscription +func TestStoreSave_SaveWithSubscription(t *testing.T) { + ctx := context.Background() + store, db := setUp(t) + + cfg := alerts.NewConfig() + cfg.SetIDFromInt64(1) + cfg.Query = "source_type=svg" + cfg.DisplayName = "bar" + err := store.Save(ctx, &alerts.SaveRequest{ + Cfg: cfg, + SubKey: &alerts.SubKey{ + SubName: "Test Subscription", + SubRevision: "abcd", + }, + }) + require.NoError(t, err) + + _, subKey, configState := getAlertFromDb(t, ctx, db, 1) + assert.Equal(t, "Test Subscription", subKey.SubName) + assert.Equal(t, "abcd", subKey.SubRevision) + assert.Equal(t, alerts.ConfigStateToInt(alerts.ACTIVE), configState) +} + +func insertAlertToDb(t *testing.T, ctx context.Context, db pool.Pool, cfg *alerts.Alert, subKey *alerts.SubKey) { + b, err := json.Marshal(cfg) + require.NoError(t, err) + + nameOrNull := sql.NullString{Valid: false} + revisionOrNull := sql.NullString{Valid: false} + + if subKey != nil { + nameOrNull.String = subKey.SubName + nameOrNull.Valid = true + revisionOrNull.String = subKey.SubRevision + revisionOrNull.Valid = true } + const query = `UPSERT INTO Alerts + (id, alert, config_state, last_modified, sub_name, sub_revision) + VALUES ($1,$2,$3,$4,$5,$6)` + if _, err := db.Exec(ctx, query, cfg.IDAsStringToInt(), string(b), cfg.StateToInt(), time.Now().Unix(), nameOrNull, revisionOrNull); err != nil { + require.NoError(t, err) + } +} + +func getAlertFromDb(t *testing.T, ctx context.Context, db pool.Pool, id int64) (*alerts.Alert, *alerts.SubKey, int) { + alert := &alerts.Alert{} + var serializedAlert string + + var nameOrNull sql.NullString + var revisionOrNull sql.NullString + var configState int + err := db.QueryRow(ctx, "SELECT alert, sub_name, sub_revision, config_state FROM Alerts WHERE id = $1", id).Scan( + &serializedAlert, + &nameOrNull, + &revisionOrNull, + &configState, + ) + require.NoError(t, err) + + err = json.Unmarshal([]byte(serializedAlert), alert) + require.NoError(t, err) + + if !nameOrNull.Valid || !revisionOrNull.Valid { + return alert, nil, configState + } + + return alert, &alerts.SubKey{ + SubName: nameOrNull.String, + SubRevision: revisionOrNull.String, + }, configState }
diff --git a/perf/go/alerts/store.go b/perf/go/alerts/store.go index 4dd6548..9fb5f29 100644 --- a/perf/go/alerts/store.go +++ b/perf/go/alerts/store.go
@@ -2,11 +2,21 @@ import "context" +type SubKey struct { + SubName string + SubRevision string +} + +type SaveRequest struct { + Cfg *Alert + SubKey *SubKey +} + // Store is the interface used to persist Alerts. type Store interface { // Save can write a new, or update an existing, Config. New Configs will // have an ID of -1. On insert the ID of the Alert will be updated. - Save(ctx context.Context, cfg *Alert) error + Save(ctx context.Context, req *SaveRequest) error // Delete removes the Alert with the given id. Delete(ctx context.Context, id int) error
diff --git a/perf/go/builders/BUILD.bazel b/perf/go/builders/BUILD.bazel index 58554ff..9fdfcf0 100644 --- a/perf/go/builders/BUILD.bazel +++ b/perf/go/builders/BUILD.bazel
@@ -61,7 +61,6 @@ deps = [ "//go/emulators/cockroachdb_instance", "//go/paramtools", - "//perf/go/alerts/alertstest", "//perf/go/config", "//perf/go/file/dirsource", "//perf/go/git/gittest",
diff --git a/perf/go/builders/builders_test.go b/perf/go/builders/builders_test.go index b0346a5..21515d3 100644 --- a/perf/go/builders/builders_test.go +++ b/perf/go/builders/builders_test.go
@@ -11,7 +11,6 @@ "go.skia.org/infra/go/emulators/cockroachdb_instance" "go.skia.org/infra/go/paramtools" - "go.skia.org/infra/perf/go/alerts/alertstest" "go.skia.org/infra/perf/go/config" "go.skia.org/infra/perf/go/file/dirsource" "go.skia.org/infra/perf/go/git/gittest" @@ -110,15 +109,6 @@ assert.Contains(t, err.Error(), invalidDataStoreType) } -func TestNewAlertStoreFromConfig_CockroachDB_Success(t *testing.T) { - ctx, instanceConfig := newCockroachDBConfigForTest(t) - - store, err := NewAlertStoreFromConfig(ctx, false, instanceConfig) - require.NoError(t, err) - - alertstest.Store_SaveListDelete(t, store) -} - func TestNewAlertStoreFromConfig_InvalidDatastoreTypeIsError(t *testing.T) { ctx, instanceConfig := newCockroachDBConfigForTest(t)
diff --git a/perf/go/frontend/frontend.go b/perf/go/frontend/frontend.go index e35279a..b02c661 100644 --- a/perf/go/frontend/frontend.go +++ b/perf/go/frontend/frontend.go
@@ -1734,7 +1734,7 @@ httputils.ReportError(w, err, "Invalid Alert", http.StatusInternalServerError) } - if err := f.alertStore.Save(ctx, cfg); err != nil { + if err := f.alertStore.Save(ctx, &alerts.SaveRequest{Cfg: cfg}); err != nil { httputils.ReportError(w, err, "Failed to save alerts.Config.", http.StatusInternalServerError) } err := json.NewEncoder(w).Encode(AlertUpdateResponse{
diff --git a/perf/go/perf-tool/application/application.go b/perf/go/perf-tool/application/application.go index a94c577..f2cb8c8 100644 --- a/perf/go/perf-tool/application/application.go +++ b/perf/go/perf-tool/application/application.go
@@ -461,7 +461,7 @@ if err != nil { return skerr.Wrap(err) } - if err := alertStore.Save(ctx, &alert); err != nil { + if err := alertStore.Save(ctx, &alerts.SaveRequest{Cfg: &alert}); err != nil { return skerr.Wrap(err) } fmt.Printf("Alerts: %q\n", alert.DisplayName)
diff --git a/perf/go/sql/expectedschema/migrate.go b/perf/go/sql/expectedschema/migrate.go index c1e42bc..5cd61d1 100644 --- a/perf/go/sql/expectedschema/migrate.go +++ b/perf/go/sql/expectedschema/migrate.go
@@ -37,17 +37,17 @@ // DO NOT DROP TABLES IN VAR BELOW. // FOR MODIFYING COLUMNS USE ADD/DROP COLUMN INSTEAD. var FromLiveToNext = ` - ALTER TABLE Regressions - ADD COLUMN migrated BOOLEAN, - ADD COLUMN regression_id TEXT; + ALTER TABLE Alerts + ADD COLUMN sub_name STRING, + ADD COLUMN sub_revision STRING; ` // ONLY DROP TABLE IF YOU JUST CREATED A NEW TABLE. // FOR MODIFYING COLUMNS USE ADD/DROP COLUMN INSTEAD. var FromNextToLive = ` - ALTER TABLE Regressions - DROP COLUMN migrated, - DROP COLUMN regression_id; + ALTER TABLE Alerts + DROP COLUMN sub_name, + DROP COLUMN sub_revision; ` // This function will check whether there's a new schema checked-in,
diff --git a/perf/go/sql/expectedschema/schema.json b/perf/go/sql/expectedschema/schema.json index ef59728..bd37323 100644 --- a/perf/go/sql/expectedschema/schema.json +++ b/perf/go/sql/expectedschema/schema.json
@@ -4,6 +4,8 @@ "alerts.config_state": "bigint def:0:::INT8 nullable:YES", "alerts.id": "bigint def:unique_rowid() nullable:NO", "alerts.last_modified": "bigint def: nullable:YES", + "alerts.sub_name": "text def: nullable:YES", + "alerts.sub_revision": "text def: nullable:YES", "anomalygroups.action": "text def: nullable:YES", "anomalygroups.action_time": "timestamp with time zone def: nullable:YES", "anomalygroups.anomaly_ids": "ARRAY def: nullable:YES",
diff --git a/perf/go/sql/expectedschema/schema_prev.json b/perf/go/sql/expectedschema/schema_prev.json index d8a50f0..ef59728 100644 --- a/perf/go/sql/expectedschema/schema_prev.json +++ b/perf/go/sql/expectedschema/schema_prev.json
@@ -39,7 +39,9 @@ "postings.trace_id": "bytea def: nullable:NO", "regressions.alert_id": "bigint def: nullable:NO", "regressions.commit_number": "bigint def: nullable:NO", + "regressions.migrated": "boolean def: nullable:YES", "regressions.regression": "text def: nullable:YES", + "regressions.regression_id": "text def: nullable:YES", "regressions2.alert_id": "bigint def: nullable:YES", "regressions2.cluster_summary": "jsonb def: nullable:YES", "regressions2.cluster_type": "text def: nullable:YES",
diff --git a/perf/go/sql/schema.go b/perf/go/sql/schema.go index 8695561..e6bfb24 100644 --- a/perf/go/sql/schema.go +++ b/perf/go/sql/schema.go
@@ -7,7 +7,9 @@ id INT PRIMARY KEY DEFAULT unique_rowid(), alert TEXT, config_state INT DEFAULT 0, - last_modified INT + last_modified INT, + sub_name STRING, + sub_revision STRING ); CREATE TABLE IF NOT EXISTS AnomalyGroups ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), @@ -121,6 +123,8 @@ "alert", "config_state", "last_modified", + "sub_name", + "sub_revision", } var AnomalyGroups = []string{
diff --git a/perf/go/sql/sql_test.go b/perf/go/sql/sql_test.go index e435f9b..8fcd37b 100644 --- a/perf/go/sql/sql_test.go +++ b/perf/go/sql/sql_test.go
@@ -92,6 +92,8 @@ commit_number INT, alert_id INT, regression TEXT, + migrated BOOL, + regression_id TEXT, PRIMARY KEY (commit_number, alert_id) ); CREATE TABLE IF NOT EXISTS Regressions2 (