From 61ea2f52bd32d5038b9eec1caf29a4d4531d03c4 Mon Sep 17 00:00:00 2001
From: Andreas Brandl <abrandl@gitlab.com>
Date: Mon, 28 May 2018 14:58:23 +0200
Subject: [PATCH] Throttle updates to Project#last_repository_updated_at.

Closes #35364.
---
 app/models/event.rb                                 |  2 ++
 ...ab-35364-throttle-updates-last-repository-at.yml |  5 +++++
 spec/models/event_spec.rb                           | 13 +++++++++++++
 3 files changed, 20 insertions(+)
 create mode 100644 changelogs/unreleased/ab-35364-throttle-updates-last-repository-at.yml

diff --git a/app/models/event.rb b/app/models/event.rb
index 741a84194e2aa..ac0b1c7b27c87 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -40,6 +40,7 @@ class Event < ActiveRecord::Base
   ).freeze
 
   RESET_PROJECT_ACTIVITY_INTERVAL = 1.hour
+  REPOSITORY_UPDATED_AT_INTERVAL = 5.minutes
 
   delegate :name, :email, :public_email, :username, to: :author, prefix: true, allow_nil: true
   delegate :title, to: :issue, prefix: true, allow_nil: true
@@ -391,6 +392,7 @@ def recent_update?
 
   def set_last_repository_updated_at
     Project.unscoped.where(id: project_id)
+      .where("last_repository_updated_at < ? OR last_repository_updated_at IS NULL", REPOSITORY_UPDATED_AT_INTERVAL.ago)
       .update_all(last_repository_updated_at: created_at)
   end
 
diff --git a/changelogs/unreleased/ab-35364-throttle-updates-last-repository-at.yml b/changelogs/unreleased/ab-35364-throttle-updates-last-repository-at.yml
new file mode 100644
index 0000000000000..8e468233637bb
--- /dev/null
+++ b/changelogs/unreleased/ab-35364-throttle-updates-last-repository-at.yml
@@ -0,0 +1,5 @@
+---
+title: Throttle updates to Project#last_repository_updated_at.
+merge_request: 19183
+author:
+type: performance
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 8ea924100228a..c1eac4fa48921 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -50,6 +50,19 @@
       end
     end
 
+    describe '#set_last_repository_updated_at' do
+      it 'only updates once every Event::REPOSITORY_UPDATED_AT_INTERVAL minutes' do
+        last_known_timestamp = (Event::REPOSITORY_UPDATED_AT_INTERVAL - 1.minute).ago
+        project.update(last_repository_updated_at: last_known_timestamp)
+        project.reload # a reload removes fractions of seconds
+
+        expect do
+          create_push_event(project, project.owner)
+          project.reload
+        end.not_to change { project.last_repository_updated_at }
+      end
+    end
+
     describe 'after_create :track_user_interacted_projects' do
       let(:event) { build(:push_event, project: project, author: project.owner) }
 
-- 
GitLab