diff --git a/database_admin/migrations/168_backport_advisories_notified.down.sql b/database_admin/migrations/168_backport_advisories_notified.down.sql new file mode 100644 index 000000000..343c5443a --- /dev/null +++ b/database_admin/migrations/168_backport_advisories_notified.down.sql @@ -0,0 +1,14 @@ +CREATE OR REPLACE FUNCTION backfill_account_advisory(rh_account_id_in INTEGER) + RETURNS VOID AS +$backfill$ +BEGIN + PERFORM refresh_account_advisory_caches_multi(NULL, rh_account_id_in); +END; +$backfill$ LANGUAGE plpgsql; + +SELECT drop_table_partition_triggers('account_advisory_sync_notified_insert', + $$BEFORE INSERT$$, + 'account_advisory', + $$FOR EACH ROW EXECUTE PROCEDURE sync_account_advisory_notified_on_insert()$$); + +DROP FUNCTION IF EXISTS sync_account_advisory_notified_on_insert(); diff --git a/database_admin/migrations/168_backport_advisories_notified.up.sql b/database_admin/migrations/168_backport_advisories_notified.up.sql new file mode 100644 index 000000000..df920713a --- /dev/null +++ b/database_admin/migrations/168_backport_advisories_notified.up.sql @@ -0,0 +1,37 @@ +CREATE OR REPLACE FUNCTION backfill_account_advisory(rh_account_id_in INTEGER) + RETURNS VOID AS +$backfill$ +BEGIN + PERFORM refresh_account_advisory_caches_multi(NULL, rh_account_id_in); + + -- copy `notified` for all `workspace_id`s per account + UPDATE account_advisory aa + SET notified = aad.notified + FROM advisory_account_data aad + WHERE aa.advisory_id = aad.advisory_id + AND aa.rh_account_id = aad.rh_account_id + AND aa.rh_account_id = rh_account_id_in + AND aad.notified IS NOT NULL; +END; +$backfill$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION sync_account_advisory_notified_on_insert() + RETURNS TRIGGER AS +$sync_notified_insert$ +BEGIN + IF NEW.notified IS NULL THEN + SELECT notified INTO NEW.notified + FROM account_advisory + WHERE rh_account_id = NEW.rh_account_id + AND advisory_id = NEW.advisory_id + AND notified IS NOT NULL + LIMIT 1; + END IF; + RETURN NEW; +END; +$sync_notified_insert$ LANGUAGE plpgsql; + +SELECT create_table_partition_triggers('account_advisory_sync_notified_insert', + $$BEFORE INSERT$$, + 'account_advisory', + $$FOR EACH ROW EXECUTE PROCEDURE sync_account_advisory_notified_on_insert()$$); diff --git a/database_admin/schema/create_schema.sql b/database_admin/schema/create_schema.sql index 8486330f0..0f1eb8f9f 100644 --- a/database_admin/schema/create_schema.sql +++ b/database_admin/schema/create_schema.sql @@ -7,7 +7,7 @@ CREATE TABLE IF NOT EXISTS schema_migrations INSERT INTO schema_migrations -VALUES (167, false); +VALUES (168, false); -- --------------------------------------------------------------------------- -- Functions @@ -229,9 +229,35 @@ CREATE OR REPLACE FUNCTION backfill_account_advisory(rh_account_id_in INTEGER) $backfill$ BEGIN PERFORM refresh_account_advisory_caches_multi(NULL, rh_account_id_in); + + -- copy `notified` for all `workspace_id`s per account + UPDATE account_advisory aa + SET notified = aad.notified + FROM advisory_account_data aad + WHERE aa.advisory_id = aad.advisory_id + AND aa.rh_account_id = aad.rh_account_id + AND aa.rh_account_id = rh_account_id_in + AND aad.notified IS NOT NULL; END; $backfill$ LANGUAGE plpgsql; +-- handle a new workspace with already notified advisory +CREATE OR REPLACE FUNCTION sync_account_advisory_notified_on_insert() + RETURNS TRIGGER AS +$sync_notified_insert$ +BEGIN + IF NEW.notified IS NULL THEN + SELECT notified INTO NEW.notified + FROM account_advisory + WHERE rh_account_id = NEW.rh_account_id + AND advisory_id = NEW.advisory_id + AND notified IS NOT NULL + LIMIT 1; + END IF; + RETURN NEW; +END; +$sync_notified_insert$ LANGUAGE plpgsql; + CREATE OR REPLACE FUNCTION refresh_system_caches(system_id_in BIGINT DEFAULT NULL, rh_account_id_in INTEGER DEFAULT NULL) RETURNS INTEGER AS @@ -901,6 +927,11 @@ SELECT grant_table_partitions('SELECT, INSERT, UPDATE, DELETE', 'account_advisor SELECT grant_table_partitions('SELECT, INSERT, UPDATE, DELETE', 'account_advisory', 'listener'); SELECT grant_table_partitions('SELECT, INSERT, UPDATE, DELETE', 'account_advisory', 'vmaas_sync'); +SELECT create_table_partition_triggers('account_advisory_sync_notified_insert', + $$BEFORE INSERT$$, + 'account_advisory', + $$FOR EACH ROW EXECUTE PROCEDURE sync_account_advisory_notified_on_insert()$$); + CREATE INDEX ON account_advisory (systems_applicable); CREATE INDEX ON account_advisory (systems_installable); CREATE INDEX ON account_advisory (advisory_id); diff --git a/evaluator/notifications.go b/evaluator/notifications.go index 4cb87a71d..2791c9b0a 100644 --- a/evaluator/notifications.go +++ b/evaluator/notifications.go @@ -76,6 +76,13 @@ func markAdvisoriesNotified(tx *gorm.DB, accountID int, advisoryIDs []int64) err if err != nil { return errors.Wrap(err, "updating notified column failed") } + // Ensure notifications are in sync between aad and aa, while we transition + err = tx.Table("account_advisory"). + Where("rh_account_id = ? AND advisory_id IN (?)", accountID, advisoryIDs). + Update("notified", time.Now()).Error + if err != nil { + return errors.Wrap(err, "updating notified column in account_advisory failed") + } return nil }