diff options
author | Rémy Coutable <remy@rymai.me> | 2017-03-07 19:35:32 +0100 |
---|---|---|
committer | Rémy Coutable <remy@rymai.me> | 2017-04-14 15:20:55 +0200 |
commit | d4da926f48503125307fe3d4a4f3952df92fc1ce (patch) | |
tree | 1a4ed961162f686f282aa173deaf4af5f7406ea6 | |
parent | cfe19b795e076b73df75ee57839640667283651c (diff) | |
download | gitlab-ce-d4da926f48503125307fe3d4a4f3952df92fc1ce.tar.gz |
Add new ScheduleUpdateUserActivityWorker and UpdateUserActivityWorker
Signed-off-by: Rémy Coutable <remy@rymai.me>
-rw-r--r-- | app/workers/schedule_update_user_activity_worker.rb | 12 | ||||
-rw-r--r-- | app/workers/update_user_activity_worker.rb | 28 | ||||
-rw-r--r-- | changelogs/unreleased-ee/27790-periodically-save-last-activity-date-data-from-redis-to-the-database.yml | 4 | ||||
-rw-r--r-- | config/initializers/1_settings.rb | 5 | ||||
-rw-r--r-- | config/sidekiq_queues.yml | 1 | ||||
-rw-r--r-- | db/migrate/20170307125949_add_last_activity_on_to_users.rb | 9 | ||||
-rw-r--r-- | db/schema.rb | 1 | ||||
-rw-r--r-- | spec/workers/schedule_update_user_activity_worker_spec.rb | 25 | ||||
-rw-r--r-- | spec/workers/update_user_activity_worker_spec.rb | 35 |
9 files changed, 120 insertions, 0 deletions
diff --git a/app/workers/schedule_update_user_activity_worker.rb b/app/workers/schedule_update_user_activity_worker.rb new file mode 100644 index 00000000000..f1adae653b1 --- /dev/null +++ b/app/workers/schedule_update_user_activity_worker.rb @@ -0,0 +1,12 @@ +class ScheduleUpdateUserActivityWorker + include Sidekiq::Worker + include CronjobQueue + + def perform(batch_size = 500) + return if Gitlab::Geo.secondary? + + Gitlab::UserActivities.new.each_slice(batch_size) do |batch| + UpdateUserActivityWorker.perform_async(Hash[batch]) + end + end +end diff --git a/app/workers/update_user_activity_worker.rb b/app/workers/update_user_activity_worker.rb new file mode 100644 index 00000000000..9f48eb46393 --- /dev/null +++ b/app/workers/update_user_activity_worker.rb @@ -0,0 +1,28 @@ +class UpdateUserActivityWorker + include Sidekiq::Worker + include DedicatedSidekiqQueue + + def perform(pairs) + return if Gitlab::Geo.secondary? + + pairs = cast_data(pairs) + ids = pairs.keys + conditions = 'WHEN id = ? THEN ? ' * ids.length + + User.where(id: ids). + update_all([ + "last_activity_on = CASE #{conditions} ELSE last_activity_on END", + *pairs.to_a.flatten + ]) + + Gitlab::UserActivities.new.delete(*ids) + end + + private + + def cast_data(pairs) + pairs.each_with_object({}) do |(key, value), new_pairs| + new_pairs[key.to_i] = Time.at(value.to_i).to_s(:db) + end + end +end diff --git a/changelogs/unreleased-ee/27790-periodically-save-last-activity-date-data-from-redis-to-the-database.yml b/changelogs/unreleased-ee/27790-periodically-save-last-activity-date-data-from-redis-to-the-database.yml new file mode 100644 index 00000000000..15e13c6f85e --- /dev/null +++ b/changelogs/unreleased-ee/27790-periodically-save-last-activity-date-data-from-redis-to-the-database.yml @@ -0,0 +1,4 @@ +--- +title: Periodically persists users activity to users.last_activity_on +merge_request: 1597 +author: diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index c19ccbb8fd8..96d39f7c4b3 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -367,6 +367,11 @@ Settings.cron_jobs['gitlab_usage_ping_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['gitlab_usage_ping_worker']['cron'] ||= Settings.send(:cron_random_weekly_time) Settings.cron_jobs['gitlab_usage_ping_worker']['job_class'] = 'GitlabUsagePingWorker' +# Every day at 00:30 +Settings.cron_jobs['schedule_update_user_activity_worker'] ||= Settingslogic.new({}) +Settings.cron_jobs['schedule_update_user_activity_worker']['cron'] ||= '30 0 * * *' +Settings.cron_jobs['schedule_update_user_activity_worker']['job_class'] = 'ScheduleUpdateUserActivityWorker' + # # GitLab Shell # diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml index 9d2066a6490..bf8964d7f68 100644 --- a/config/sidekiq_queues.yml +++ b/config/sidekiq_queues.yml @@ -53,3 +53,4 @@ - [default, 1] - [pages, 1] - [system_hook_push, 1] + - [update_user_activity, 1] diff --git a/db/migrate/20170307125949_add_last_activity_on_to_users.rb b/db/migrate/20170307125949_add_last_activity_on_to_users.rb new file mode 100644 index 00000000000..0100836b473 --- /dev/null +++ b/db/migrate/20170307125949_add_last_activity_on_to_users.rb @@ -0,0 +1,9 @@ +class AddLastActivityOnToUsers < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def change + add_column :users, :last_activity_on, :date + end +end diff --git a/db/schema.rb b/db/schema.rb index 1c592dd5d6d..9ce9df68de8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1303,6 +1303,7 @@ ActiveRecord::Schema.define(version: 20170408033905) do t.string "organization" t.boolean "authorized_projects_populated" t.boolean "ghost" + t.date "last_activity_on" t.boolean "notified_of_own_activity" t.boolean "require_two_factor_authentication_from_group", default: false, null: false t.integer "two_factor_grace_period", default: 48, null: false diff --git a/spec/workers/schedule_update_user_activity_worker_spec.rb b/spec/workers/schedule_update_user_activity_worker_spec.rb new file mode 100644 index 00000000000..e583c3203aa --- /dev/null +++ b/spec/workers/schedule_update_user_activity_worker_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe ScheduleUpdateUserActivityWorker, :redis do + let(:now) { Time.now } + + before do + Gitlab::UserActivities.record('1', now) + Gitlab::UserActivities.record('2', now) + end + + it 'schedules UpdateUserActivityWorker once' do + expect(UpdateUserActivityWorker).to receive(:perform_async).with({ '1' => now.to_i.to_s, '2' => now.to_i.to_s }) + + subject.perform + end + + context 'when specifying a batch size' do + it 'schedules UpdateUserActivityWorker twice' do + expect(UpdateUserActivityWorker).to receive(:perform_async).with({ '1' => now.to_i.to_s }) + expect(UpdateUserActivityWorker).to receive(:perform_async).with({ '2' => now.to_i.to_s }) + + subject.perform(1) + end + end +end diff --git a/spec/workers/update_user_activity_worker_spec.rb b/spec/workers/update_user_activity_worker_spec.rb new file mode 100644 index 00000000000..43e9511f116 --- /dev/null +++ b/spec/workers/update_user_activity_worker_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe UpdateUserActivityWorker, :redis do + let(:user_active_2_days_ago) { create(:user, current_sign_in_at: 10.months.ago) } + let(:user_active_yesterday_1) { create(:user) } + let(:user_active_yesterday_2) { create(:user) } + let(:user_active_today) { create(:user) } + let(:data) do + { + user_active_2_days_ago.id.to_s => 2.days.ago.at_midday.to_i.to_s, + user_active_yesterday_1.id.to_s => 1.day.ago.at_midday.to_i.to_s, + user_active_yesterday_2.id.to_s => 1.day.ago.at_midday.to_i.to_s, + user_active_today.id.to_s => Time.now.to_i.to_s + } + end + + it 'updates users.last_activity_on' do + subject.perform(data) + + aggregate_failures do + expect(user_active_2_days_ago.reload.last_activity_on).to eq(2.days.ago.to_date) + expect(user_active_yesterday_1.reload.last_activity_on).to eq(1.day.ago.to_date) + expect(user_active_yesterday_2.reload.last_activity_on).to eq(1.day.ago.to_date) + expect(user_active_today.reload.reload.last_activity_on).to eq(Date.today) + end + end + + it 'deletes the pairs from Redis' do + data.each { |id, time| Gitlab::UserActivities.record(id, time) } + + subject.perform(data) + + expect(Gitlab::UserActivities.new.to_a).to be_empty + end +end |