From 03e335c381005b51492f028087dfc503792d46d1 Mon Sep 17 00:00:00 2001 From: Nick LaMuro Date: Thu, 12 Apr 2018 18:09:26 -0500 Subject: [PATCH] Adds purging for notifications * Sets notifications that are older than a week to be purged by default. * Purging is run daily * Clears out notification recipients as well --- app/models/miq_schedule_worker/jobs.rb | 4 +++ app/models/miq_schedule_worker/runner.rb | 5 +++ app/models/notification.rb | 2 ++ app/models/notification/purging.rb | 24 ++++++++++++++ config/settings.yml | 5 +++ spec/models/notification/purging_spec.rb | 40 ++++++++++++++++++++++++ 6 files changed, 80 insertions(+) create mode 100644 app/models/notification/purging.rb create mode 100644 spec/models/notification/purging_spec.rb diff --git a/app/models/miq_schedule_worker/jobs.rb b/app/models/miq_schedule_worker/jobs.rb index 953176c93d1..1b23fe49ecf 100644 --- a/app/models/miq_schedule_worker/jobs.rb +++ b/app/models/miq_schedule_worker/jobs.rb @@ -113,6 +113,10 @@ def event_stream_purge_timer queue_work(:class_name => "EventStream", :method_name => "purge_timer", :zone => nil) end + def notification_purge_timer + queue_work(:class_name => "Notification", :method_name => "purge_timer", :zone => nil) + end + def policy_event_purge_timer queue_work(:class_name => "PolicyEvent", :method_name => "purge_timer", :zone => nil) end diff --git a/app/models/miq_schedule_worker/runner.rb b/app/models/miq_schedule_worker/runner.rb index 95c4b33f25c..e85f2986c27 100644 --- a/app/models/miq_schedule_worker/runner.rb +++ b/app/models/miq_schedule_worker/runner.rb @@ -228,6 +228,11 @@ def schedules_for_scheduler_role enqueue :archived_entities_purge_timer end + every = worker_settings[:notifications_purge_interval] + scheduler.schedule_every(every, :first_in => every) do + enqueue(:notification_purge_timer) + end + # Schedule every 24 hours at = worker_settings[:storage_file_collection_time_utc] if Time.now.strftime("%Y-%m-%d #{at}").to_time(:utc) < Time.now.utc diff --git a/app/models/notification.rb b/app/models/notification.rb index eb69d4da4f0..ebd1b224c2c 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -1,4 +1,6 @@ class Notification < ApplicationRecord + include_concern 'Purging' + belongs_to :notification_type belongs_to :initiator, :class_name => User, :foreign_key => 'user_id' belongs_to :subject, :polymorphic => true diff --git a/app/models/notification/purging.rb b/app/models/notification/purging.rb new file mode 100644 index 00000000000..e7e605ed1e7 --- /dev/null +++ b/app/models/notification/purging.rb @@ -0,0 +1,24 @@ +class Notification + module Purging + extend ActiveSupport::Concern + include PurgingMixin + + module ClassMethods + def purge_date + ::Settings.notifications.history.keep_notifications.to_i_with_method.seconds.ago.utc + end + + def purge_window_size + ::Settings.notifications.history.purge_window_size + end + + def purge_scope(older_than) + where(arel_table[:created_at].lt(older_than)) + end + + def purge_associated_records(ids) + NotificationRecipient.where(:notification_id => ids).delete_all + end + end + end +end diff --git a/config/settings.yml b/config/settings.yml index 6d8c5f244a2..9f3ef8c9bc7 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -1029,6 +1029,10 @@ :level_websocket_in_evm: error :level_vcloud: info :level_vcloud_in_evm: error +:notifications: + :history: + :purge_window_size: 1000 + :keep_notifications: 1.week :management_system: :power_operation_expiration: 10.minutes :performance: @@ -1421,6 +1425,7 @@ :log_database_statistics_interval: 1.days :memory_threshold: 500.megabytes :nice_delta: 3 + :notifications_purge_interval: 1.day :orchestration_stack_retired_interval: 10.minutes :performance_collection_interval: 3.minutes :performance_collection_start_delay: 5.minutes diff --git a/spec/models/notification/purging_spec.rb b/spec/models/notification/purging_spec.rb new file mode 100644 index 00000000000..de0a01ca149 --- /dev/null +++ b/spec/models/notification/purging_spec.rb @@ -0,0 +1,40 @@ +describe Notification do + context "::Purging" do + describe ".purge_by_date" do + it "purges old notifications" do + FactoryGirl.create(:user) + FactoryGirl.create(:user) + type = FactoryGirl.create(:notification_type, :audience => NotificationType::AUDIENCE_GLOBAL) + + # Notification and recipients that will not be purged + new_notification = FactoryGirl.create(:notification, :notification_type => type) + + old_notification, semi_old_notification = nil + Timecop.freeze(6.days.ago) do + semi_old_notification = FactoryGirl.create(:notification, :notification_type => type) + end + + Timecop.freeze(8.days.ago) do + # Notification and recipients that will be purged + old_notification = FactoryGirl.create(:notification, :notification_type => type) + end + + expect(described_class.all).to match_array([new_notification, semi_old_notification, old_notification]) + expect(NotificationRecipient.count).to eq(6) + count = described_class.purge_by_date(described_class.purge_date) + expect(described_class.all).to match_array([new_notification, semi_old_notification]) + expect(NotificationRecipient.count).to eq(4) + expect(count).to eq(1) + end + end + + describe ".purge_timer" do + it "queues the correct purge method" do + EvmSpecHelper.local_miq_server + described_class.purge_timer + q = MiqQueue.first + expect(q).to have_attributes(:class_name => described_class.name, :method_name => "purge_by_date") + end + end + end +end