From fdc3ff7c2d538751fc5e761fae33fc007294a540 Mon Sep 17 00:00:00 2001
From: Eugen Rochko <eugen@zeonfederated.com>
Date: Wed, 12 Jul 2023 17:06:00 +0200
Subject: [PATCH] Change notifications API to use a replica (#25874)
---
app/controllers/api/v1/notifications_controller.rb | 8 ++++++--
app/controllers/api/v1/timelines/home_controller.rb | 2 +-
app/controllers/application_controller.rb | 1 +
app/helpers/database_helper.rb | 11 +++++++++++
app/workers/feed_insert_worker.rb | 5 +++--
app/workers/merge_worker.rb | 5 +++--
app/workers/regeneration_worker.rb | 5 +++--
app/workers/unmerge_worker.rb | 5 +++--
8 files changed, 31 insertions(+), 11 deletions(-)
create mode 100644 app/helpers/database_helper.rb
diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb
index 8414f6b25c..406ab97538 100644
--- a/app/controllers/api/v1/notifications_controller.rb
+++ b/app/controllers/api/v1/notifications_controller.rb
@@ -9,8 +9,12 @@ class Api::V1::NotificationsController < Api::BaseController
DEFAULT_NOTIFICATIONS_LIMIT = 40
def index
- @notifications = load_notifications
- render json: @notifications, each_serializer: REST::NotificationSerializer, relationships: StatusRelationshipsPresenter.new(target_statuses_from_notifications, current_user&.account_id)
+ with_read_replica do
+ @notifications = load_notifications
+ @relationships = StatusRelationshipsPresenter.new(target_statuses_from_notifications, current_user&.account_id)
+ end
+
+ render json: @notifications, each_serializer: REST::NotificationSerializer, relationships: @relationships
end
def show
diff --git a/app/controllers/api/v1/timelines/home_controller.rb b/app/controllers/api/v1/timelines/home_controller.rb
index 0ee28ef042..83b8cb4c66 100644
--- a/app/controllers/api/v1/timelines/home_controller.rb
+++ b/app/controllers/api/v1/timelines/home_controller.rb
@@ -6,7 +6,7 @@ class Api::V1::Timelines::HomeController < Api::BaseController
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
def show
- ApplicationRecord.connected_to(role: :read, prevent_writes: true) do
+ with_read_replica do
@statuses = load_statuses
@relationships = StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index f966b18ab5..66886b4519 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -10,6 +10,7 @@ class ApplicationController < ActionController::Base
include SessionTrackingConcern
include CacheConcern
include DomainControlHelper
+ include DatabaseHelper
helper_method :current_account
helper_method :current_session
diff --git a/app/helpers/database_helper.rb b/app/helpers/database_helper.rb
new file mode 100644
index 0000000000..965eeaf41d
--- /dev/null
+++ b/app/helpers/database_helper.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module DatabaseHelper
+ def with_read_replica(&block)
+ ApplicationRecord.connected_to(role: :read, prevent_writes: true, &block)
+ end
+
+ def with_primary(&block)
+ ApplicationRecord.connected_to(role: :primary, &block)
+ end
+end
diff --git a/app/workers/feed_insert_worker.rb b/app/workers/feed_insert_worker.rb
index 47826c2111..fd7dbd30da 100644
--- a/app/workers/feed_insert_worker.rb
+++ b/app/workers/feed_insert_worker.rb
@@ -2,9 +2,10 @@
class FeedInsertWorker
include Sidekiq::Worker
+ include DatabaseHelper
def perform(status_id, id, type = 'home', options = {})
- ApplicationRecord.connected_to(role: :primary) do
+ with_primary do
@type = type.to_sym
@status = Status.find(status_id)
@options = options.symbolize_keys
@@ -18,7 +19,7 @@ class FeedInsertWorker
end
end
- ApplicationRecord.connected_to(role: :read, prevent_writes: true) do
+ with_read_replica do
check_and_insert
end
rescue ActiveRecord::RecordNotFound
diff --git a/app/workers/merge_worker.rb b/app/workers/merge_worker.rb
index 50cfcc3f06..8e1614ad21 100644
--- a/app/workers/merge_worker.rb
+++ b/app/workers/merge_worker.rb
@@ -3,14 +3,15 @@
class MergeWorker
include Sidekiq::Worker
include Redisable
+ include DatabaseHelper
def perform(from_account_id, into_account_id)
- ApplicationRecord.connected_to(role: :primary) do
+ with_primary do
@from_account = Account.find(from_account_id)
@into_account = Account.find(into_account_id)
end
- ApplicationRecord.connected_to(role: :read, prevent_writes: true) do
+ with_read_replica do
FeedManager.instance.merge_into_home(@from_account, @into_account)
end
rescue ActiveRecord::RecordNotFound
diff --git a/app/workers/regeneration_worker.rb b/app/workers/regeneration_worker.rb
index 5ac095e65f..4228f897d3 100644
--- a/app/workers/regeneration_worker.rb
+++ b/app/workers/regeneration_worker.rb
@@ -2,15 +2,16 @@
class RegenerationWorker
include Sidekiq::Worker
+ include DatabaseHelper
sidekiq_options lock: :until_executed
def perform(account_id, _ = :home)
- ApplicationRecord.connected_to(role: :primary) do
+ with_primary do
@account = Account.find(account_id)
end
- ApplicationRecord.connected_to(role: :read, prevent_writes: true) do
+ with_read_replica do
PrecomputeFeedService.new.call(@account)
end
rescue ActiveRecord::RecordNotFound
diff --git a/app/workers/unmerge_worker.rb b/app/workers/unmerge_worker.rb
index f911ea2f91..e8ac535dfe 100644
--- a/app/workers/unmerge_worker.rb
+++ b/app/workers/unmerge_worker.rb
@@ -2,16 +2,17 @@
class UnmergeWorker
include Sidekiq::Worker
+ include DatabaseHelper
sidekiq_options queue: 'pull'
def perform(from_account_id, into_account_id)
- ApplicationRecord.connected_to(role: :primary) do
+ with_primary do
@from_account = Account.find(from_account_id)
@into_account = Account.find(into_account_id)
end
- ApplicationRecord.connected_to(role: :read, prevent_writes: true) do
+ with_read_replica do
FeedManager.instance.unmerge_from_home(@from_account, @into_account)
end
rescue ActiveRecord::RecordNotFound
--
GitLab