Remove event caching code
Flushing the events cache worked by updating a recent number of rows in the "events" table. This has the result that on PostgreSQL a lot of dead tuples are produced on a regular basis. This in turn means that PostgreSQL will spend considerable amounts of time vacuuming this table. This in turn can lead to an increase of database load. For GitLab.com we measured the impact of not using events caching and found no measurable increase in response timings. Meanwhile not flushing the events cache lead to the "events" table having no more dead tuples as now rows are only inserted into this table. As a result of this we are hereby removing events caching as it does not appear to help and only increases database load. For more information see the following comment: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6578#note_18864037
This commit is contained in:
parent
d7eeb6df51
commit
5371da341e
15 changed files with 13 additions and 99 deletions
|
@ -4,7 +4,6 @@ class Profiles::AvatarsController < Profiles::ApplicationController
|
||||||
@user.remove_avatar!
|
@user.remove_avatar!
|
||||||
|
|
||||||
@user.save
|
@user.save
|
||||||
@user.reset_events_cache
|
|
||||||
|
|
||||||
redirect_to profile_path
|
redirect_to profile_path
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,7 +20,6 @@ class Projects::AvatarsController < Projects::ApplicationController
|
||||||
@project.remove_avatar!
|
@project.remove_avatar!
|
||||||
|
|
||||||
@project.save
|
@project.save
|
||||||
@project.reset_events_cache
|
|
||||||
|
|
||||||
redirect_to edit_project_path(@project)
|
redirect_to edit_project_path(@project)
|
||||||
end
|
end
|
||||||
|
|
|
@ -43,12 +43,6 @@ class Event < ActiveRecord::Base
|
||||||
scope :for_milestone_id, ->(milestone_id) { where(target_type: "Milestone", target_id: milestone_id) }
|
scope :for_milestone_id, ->(milestone_id) { where(target_type: "Milestone", target_id: milestone_id) }
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def reset_event_cache_for(target)
|
|
||||||
Event.where(target_id: target.id, target_type: target.class.to_s).
|
|
||||||
order('id DESC').limit(100).
|
|
||||||
update_all(updated_at: Time.now)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Update Gitlab::ContributionsCalendar#activity_dates if this changes
|
# Update Gitlab::ContributionsCalendar#activity_dates if this changes
|
||||||
def contributions
|
def contributions
|
||||||
where("action = ? OR (target_type in (?) AND action in (?))",
|
where("action = ? OR (target_type in (?) AND action in (?))",
|
||||||
|
|
|
@ -182,18 +182,6 @@ class Issue < ActiveRecord::Base
|
||||||
branches_with_iid - branches_with_merge_request
|
branches_with_iid - branches_with_merge_request
|
||||||
end
|
end
|
||||||
|
|
||||||
# Reset issue events cache
|
|
||||||
#
|
|
||||||
# Since we do cache @event we need to reset cache in special cases:
|
|
||||||
# * when an issue is updated
|
|
||||||
# Events cache stored like events/23-20130109142513.
|
|
||||||
# The cache key includes updated_at timestamp.
|
|
||||||
# Thus it will automatically generate a new fragment
|
|
||||||
# when the event is updated because the key changes.
|
|
||||||
def reset_events_cache
|
|
||||||
Event.reset_event_cache_for(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
# To allow polymorphism with MergeRequest.
|
# To allow polymorphism with MergeRequest.
|
||||||
def source_project
|
def source_project
|
||||||
project
|
project
|
||||||
|
|
|
@ -601,18 +601,6 @@ class MergeRequest < ActiveRecord::Base
|
||||||
self.target_project.repository.branch_names.include?(self.target_branch)
|
self.target_project.repository.branch_names.include?(self.target_branch)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Reset merge request events cache
|
|
||||||
#
|
|
||||||
# Since we do cache @event we need to reset cache in special cases:
|
|
||||||
# * when a merge request is updated
|
|
||||||
# Events cache stored like events/23-20130109142513.
|
|
||||||
# The cache key includes updated_at timestamp.
|
|
||||||
# Thus it will automatically generate a new fragment
|
|
||||||
# when the event is updated because the key changes.
|
|
||||||
def reset_events_cache
|
|
||||||
Event.reset_event_cache_for(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
def merge_commit_message
|
def merge_commit_message
|
||||||
message = "Merge branch '#{source_branch}' into '#{target_branch}'\n\n"
|
message = "Merge branch '#{source_branch}' into '#{target_branch}'\n\n"
|
||||||
message << "#{title}\n\n"
|
message << "#{title}\n\n"
|
||||||
|
|
|
@ -198,19 +198,6 @@ class Note < ActiveRecord::Base
|
||||||
super(noteable_type.to_s.classify.constantize.base_class.to_s)
|
super(noteable_type.to_s.classify.constantize.base_class.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Reset notes events cache
|
|
||||||
#
|
|
||||||
# Since we do cache @event we need to reset cache in special cases:
|
|
||||||
# * when a note is updated
|
|
||||||
# * when a note is removed
|
|
||||||
# Events cache stored like events/23-20130109142513.
|
|
||||||
# The cache key includes updated_at timestamp.
|
|
||||||
# Thus it will automatically generate a new fragment
|
|
||||||
# when the event is updated because the key changes.
|
|
||||||
def reset_events_cache
|
|
||||||
Event.reset_event_cache_for(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
def editable?
|
def editable?
|
||||||
!system?
|
!system?
|
||||||
end
|
end
|
||||||
|
|
|
@ -973,7 +973,6 @@ class Project < ActiveRecord::Base
|
||||||
begin
|
begin
|
||||||
gitlab_shell.mv_repository(repository_storage_path, "#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki")
|
gitlab_shell.mv_repository(repository_storage_path, "#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki")
|
||||||
send_move_instructions(old_path_with_namespace)
|
send_move_instructions(old_path_with_namespace)
|
||||||
reset_events_cache
|
|
||||||
|
|
||||||
@old_path_with_namespace = old_path_with_namespace
|
@old_path_with_namespace = old_path_with_namespace
|
||||||
|
|
||||||
|
@ -1040,22 +1039,6 @@ class Project < ActiveRecord::Base
|
||||||
attrs
|
attrs
|
||||||
end
|
end
|
||||||
|
|
||||||
# Reset events cache related to this project
|
|
||||||
#
|
|
||||||
# Since we do cache @event we need to reset cache in special cases:
|
|
||||||
# * when project was moved
|
|
||||||
# * when project was renamed
|
|
||||||
# * when the project avatar changes
|
|
||||||
# Events cache stored like events/23-20130109142513.
|
|
||||||
# The cache key includes updated_at timestamp.
|
|
||||||
# Thus it will automatically generate a new fragment
|
|
||||||
# when the event is updated because the key changes.
|
|
||||||
def reset_events_cache
|
|
||||||
Event.where(project_id: self.id).
|
|
||||||
order('id DESC').limit(100).
|
|
||||||
update_all(updated_at: Time.now)
|
|
||||||
end
|
|
||||||
|
|
||||||
def project_member(user)
|
def project_member(user)
|
||||||
project_members.find_by(user_id: user)
|
project_members.find_by(user_id: user)
|
||||||
end
|
end
|
||||||
|
|
|
@ -704,20 +704,6 @@ class User < ActiveRecord::Base
|
||||||
project.project_member(self)
|
project.project_member(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Reset project events cache related to this user
|
|
||||||
#
|
|
||||||
# Since we do cache @event we need to reset cache in special cases:
|
|
||||||
# * when the user changes their avatar
|
|
||||||
# Events cache stored like events/23-20130109142513.
|
|
||||||
# The cache key includes updated_at timestamp.
|
|
||||||
# Thus it will automatically generate a new fragment
|
|
||||||
# when the event is updated because the key changes.
|
|
||||||
def reset_events_cache
|
|
||||||
Event.where(author_id: id).
|
|
||||||
order('id DESC').limit(1000).
|
|
||||||
update_all(updated_at: Time.now)
|
|
||||||
end
|
|
||||||
|
|
||||||
def full_website_url
|
def full_website_url
|
||||||
return "http://#{website_url}" if website_url !~ /\Ahttps?:\/\//
|
return "http://#{website_url}" if website_url !~ /\Ahttps?:\/\//
|
||||||
|
|
||||||
|
|
|
@ -184,8 +184,6 @@ class IssuableBaseService < BaseService
|
||||||
params[:label_ids] = process_label_ids(params, existing_label_ids: issuable.label_ids)
|
params[:label_ids] = process_label_ids(params, existing_label_ids: issuable.label_ids)
|
||||||
|
|
||||||
if params.present? && update_issuable(issuable, params)
|
if params.present? && update_issuable(issuable, params)
|
||||||
issuable.reset_events_cache
|
|
||||||
|
|
||||||
# We do not touch as it will affect a update on updated_at field
|
# We do not touch as it will affect a update on updated_at field
|
||||||
ActiveRecord::Base.no_touching do
|
ActiveRecord::Base.no_touching do
|
||||||
handle_common_system_notes(issuable, old_labels: old_labels)
|
handle_common_system_notes(issuable, old_labels: old_labels)
|
||||||
|
|
|
@ -2,7 +2,6 @@ module Notes
|
||||||
class DeleteService < BaseService
|
class DeleteService < BaseService
|
||||||
def execute(note)
|
def execute(note)
|
||||||
note.destroy
|
note.destroy
|
||||||
note.reset_events_cache
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,6 @@ module Notes
|
||||||
|
|
||||||
note.update_attributes(params.merge(updated_by: current_user))
|
note.update_attributes(params.merge(updated_by: current_user))
|
||||||
note.create_new_cross_references!(current_user)
|
note.create_new_cross_references!(current_user)
|
||||||
note.reset_events_cache
|
|
||||||
|
|
||||||
if note.previous_changes.include?('note')
|
if note.previous_changes.include?('note')
|
||||||
TodoService.new.update_note(note, current_user)
|
TodoService.new.update_note(note, current_user)
|
||||||
|
|
|
@ -61,9 +61,6 @@ module Projects
|
||||||
# Move missing group labels to project
|
# Move missing group labels to project
|
||||||
Labels::TransferService.new(current_user, old_group, project).execute
|
Labels::TransferService.new(current_user, old_group, project).execute
|
||||||
|
|
||||||
# clear project cached events
|
|
||||||
project.reset_events_cache
|
|
||||||
|
|
||||||
# Move uploads
|
# Move uploads
|
||||||
Gitlab::UploadsTransfer.new.move_project(project.path, old_namespace.path, new_namespace.path)
|
Gitlab::UploadsTransfer.new.move_project(project.path, old_namespace.path, new_namespace.path)
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,10 @@ class AvatarUploader < CarrierWave::Uploader::Base
|
||||||
|
|
||||||
storage :file
|
storage :file
|
||||||
|
|
||||||
after :store, :reset_events_cache
|
|
||||||
|
|
||||||
def store_dir
|
def store_dir
|
||||||
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset_events_cache(file)
|
|
||||||
model.reset_events_cache if model.is_a?(User)
|
|
||||||
end
|
|
||||||
|
|
||||||
def exists?
|
def exists?
|
||||||
model.avatar.file && model.avatar.file.exists?
|
model.avatar.file && model.avatar.file.exists?
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,14 +3,13 @@
|
||||||
.event-item-timestamp
|
.event-item-timestamp
|
||||||
#{time_ago_with_tooltip(event.created_at)}
|
#{time_ago_with_tooltip(event.created_at)}
|
||||||
|
|
||||||
= cache [event, current_application_settings, "v2.2"] do
|
= author_avatar(event, size: 40)
|
||||||
= author_avatar(event, size: 40)
|
|
||||||
|
|
||||||
- if event.created_project?
|
- if event.created_project?
|
||||||
= render "events/event/created_project", event: event
|
= render "events/event/created_project", event: event
|
||||||
- elsif event.push?
|
- elsif event.push?
|
||||||
= render "events/event/push", event: event
|
= render "events/event/push", event: event
|
||||||
- elsif event.commented?
|
- elsif event.commented?
|
||||||
= render "events/event/note", event: event
|
= render "events/event/note", event: event
|
||||||
- else
|
- else
|
||||||
= render "events/event/common", event: event
|
= render "events/event/common", event: event
|
||||||
|
|
4
changelogs/unreleased/events-cache-invalidation.yml
Normal file
4
changelogs/unreleased/events-cache-invalidation.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Remove caching of events data
|
||||||
|
merge_request: 6578
|
||||||
|
author:
|
Loading…
Reference in a new issue