Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémy Coutable <remy@rymai.me>2017-03-07 21:35:32 +0300
committerRémy Coutable <remy@rymai.me>2017-04-14 16:20:55 +0300
commitd4da926f48503125307fe3d4a4f3952df92fc1ce (patch)
tree1a4ed961162f686f282aa173deaf4af5f7406ea6
parentcfe19b795e076b73df75ee57839640667283651c (diff)
Add new ScheduleUpdateUserActivityWorker and UpdateUserActivityWorker
Signed-off-by: Rémy Coutable <remy@rymai.me>
-rw-r--r--app/workers/schedule_update_user_activity_worker.rb12
-rw-r--r--app/workers/update_user_activity_worker.rb28
-rw-r--r--changelogs/unreleased-ee/27790-periodically-save-last-activity-date-data-from-redis-to-the-database.yml4
-rw-r--r--config/initializers/1_settings.rb5
-rw-r--r--config/sidekiq_queues.yml1
-rw-r--r--db/migrate/20170307125949_add_last_activity_on_to_users.rb9
-rw-r--r--db/schema.rb1
-rw-r--r--spec/workers/schedule_update_user_activity_worker_spec.rb25
-rw-r--r--spec/workers/update_user_activity_worker_spec.rb35
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