Compare commits

...
Author SHA1 Message Date
Vishnu Narayanan 0ef3b3b5b5 fix: force build_contact and increment_view_count methods to use writing role
These methods are used by the widget to create a contact and helpcenter to
increment the view count. Since these methods are triggered by GET
request, Rails will use the reading role which will fail if the table
is readonly.
2024-05-24 17:31:35 +05:30
Vishnu NarayananandGitHub af084af774 Merge branch 'develop' into feat/add_read_replica_support 2024-05-16 08:41:13 +05:30
Vishnu Narayanan 5a682135f2 feat: configure auto db switching 2024-05-07 16:37:41 +10:00
Vishnu NarayananandGitHub a72dba1769 Merge branch 'develop' into feat/add_read_replica_support 2024-05-07 12:33:32 +10:00
Vishnu NarayananandGitHub cc653e072a Merge branch 'develop' into feat/add_read_replica_support 2024-05-03 14:39:38 +10:00
Vishnu Narayanan 7e64671a27 chore: add replica settings for test&dev 2024-05-03 14:37:37 +10:00
Vishnu Narayanan 43bca252f9 chore: revert db fallback initializer 2024-05-03 13:36:37 +10:00
Vishnu Narayanan 5dc74ff40f chore: debug gh action 2024-05-03 12:34:12 +10:00
Vishnu Narayanan 8dd735f3ea chore: debug gh action 2024-05-03 12:29:33 +10:00
Vishnu Narayanan ce69614662 Merge branch 'feat/add_read_replica_support' of github.com:chatwoot/chatwoot into feat/add_read_replica_support 2024-05-03 12:26:13 +10:00
Vishnu Narayanan 8a6b13fd85 chore: debug gh action 2024-05-03 12:25:47 +10:00
Vishnu NarayananandGitHub 2692dba5bd Merge branch 'develop' into feat/add_read_replica_support 2024-05-03 11:54:54 +10:00
Vishnu Narayanan 0095254e65 feat: handle if read_replica is not available 2024-05-02 18:59:42 +10:00
Vishnu Narayanan 3b34be5740 feat: add read replica support 2024-05-02 18:46:46 +10:00
8 changed files with 78 additions and 17 deletions
+7
View File
@@ -57,6 +57,13 @@ POSTGRES_PASSWORD=
RAILS_ENV=development
# Changes the Postgres query timeout limit. The default is 14 seconds. Modify only when required.
# POSTGRES_STATEMENT_TIMEOUT=14s
# read replica configuration for production
# POSTGRES_HOST_RR=postgres_rr
# create a new user with readonly permissions
# POSTGRES_USERNAME_RR=postgres_readonly
# POSTGRES_PASSWORD_RR=
RAILS_MAX_THREADS=5
# The email from which all outgoing emails are sent
-1
View File
@@ -45,7 +45,6 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
+4 -2
View File
@@ -47,8 +47,10 @@ class WidgetsController < ActionController::Base
def build_contact
return if @contact.present?
@contact_inbox, @token = build_contact_inbox_with_token(@web_widget, additional_attributes)
@contact = @contact_inbox.contact
ActiveRecord::Base.connected_to(role: :writing) do
@contact_inbox, @token = build_contact_inbox_with_token(@web_widget, additional_attributes)
@contact = @contact_inbox.contact
end
end
def ensure_account_is_active
+2
View File
@@ -2,6 +2,8 @@ class ApplicationRecord < ActiveRecord::Base
include Events::Types
self.abstract_class = true
connects_to database: { writing: :primary, reading: :primary_replica }
before_validation :validates_column_content_length
# the models that exposed in email templates through liquid
+4 -2
View File
@@ -114,8 +114,10 @@ class Article < ApplicationRecord
def increment_view_count
# rubocop:disable Rails/SkipsModelValidations
update_column(:views, views? ? views + 1 : 1)
# rubocop:enable Rails/SkipsModelValidations
ActiveRecord::Base.connected_to(role: :writing) do
update_column(:views, views? ? views + 1 : 1)
# rubocop:enable Rails/SkipsModelValidations
end
end
def self.update_positions(positions_hash)
+34 -12
View File
@@ -10,19 +10,41 @@ default: &default
statement_timeout: <%= ENV["POSTGRES_STATEMENT_TIMEOUT"] || "14s" %>
development:
<<: *default
database: "<%= ENV.fetch('POSTGRES_DATABASE', 'chatwoot_dev') %>"
username: "<%= ENV.fetch('POSTGRES_USERNAME', 'postgres') %>"
password: "<%= ENV.fetch('POSTGRES_PASSWORD', '') %>"
primary:
<<: *default
database: "<%= ENV.fetch('POSTGRES_DATABASE', 'chatwoot_dev') %>"
username: "<%= ENV.fetch('POSTGRES_USERNAME', 'postgres') %>"
password: "<%= ENV.fetch('POSTGRES_PASSWORD', '') %>"
primary_replica:
<<: *default
database: "<%= ENV.fetch('POSTGRES_DATABASE', 'chatwoot_dev') %>"
username: "<%= ENV.fetch('POSTGRES_USERNAME', 'postgres') %>"
password: "<%= ENV.fetch('POSTGRES_PASSWORD', '') %>"
replica: true
test:
<<: *default
database: "<%= ENV.fetch('POSTGRES_DATABASE', 'chatwoot_test') %>"
username: "<%= ENV.fetch('POSTGRES_USERNAME', 'postgres') %>"
password: "<%= ENV.fetch('POSTGRES_PASSWORD', '') %>"
primary:
<<: *default
database: "<%= ENV.fetch('POSTGRES_DATABASE', 'chatwoot_test') %>"
username: "<%= ENV.fetch('POSTGRES_USERNAME', 'postgres') %>"
password: "<%= ENV.fetch('POSTGRES_PASSWORD', '') %>"
primary_replica:
<<: *default
database: "<%= ENV.fetch('POSTGRES_DATABASE', 'chatwoot_test') %>"
username: "<%= ENV.fetch('POSTGRES_USERNAME', 'postgres') %>"
password: "<%= ENV.fetch('POSTGRES_PASSWORD', '') %>"
replica: true
production:
<<: *default
database: "<%= ENV.fetch('POSTGRES_DATABASE', 'chatwoot_production') %>"
username: "<%= ENV.fetch('POSTGRES_USERNAME', 'chatwoot_prod') %>"
password: "<%= ENV.fetch('POSTGRES_PASSWORD', 'chatwoot_prod') %>"
primary:
<<: *default
database: "<%= ENV.fetch('POSTGRES_DATABASE', 'chatwoot_production') %>"
username: "<%= ENV.fetch('POSTGRES_USERNAME', 'chatwoot_prod') %>"
password: "<%= ENV.fetch('POSTGRES_PASSWORD', 'chatwoot_prod') %>"
primary_replica:
<<: *default
host: "<%= ENV.fetch('POSTGRES_HOST_RR', nil) %>"
database: "<%= ENV.fetch('POSTGRES_DATABASE', nil) %>"
username: "<%= ENV.fetch('POSTGRES_USERNAME_RR', nil) %>"
password: "<%= ENV.fetch('POSTGRES_PASSWORD_RR', nil) %>"
replica: true
+4
View File
@@ -70,6 +70,10 @@ Rails.application.configure do
# require 'syslog/logger'
config.logger = ActiveSupport::Logger.new(Rails.root.join('log', "#{Rails.env}.log"), 1, ENV.fetch('LOG_SIZE', '1024').to_i.megabytes)
config.active_record.database_selector = { delay: 2.seconds }
config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
# Bullet configuration to fix the N+1 queries
config.after_initialize do
Bullet.enable = true
+23
View File
@@ -102,5 +102,28 @@ Rails.application.configure do
# :sendgrid for Sendgrid
config.action_mailbox.ingress = ENV.fetch('RAILS_INBOUND_EMAIL_SERVICE', 'relay').to_sym
# Enable Database Selector
#
# Inserts middleware to perform automatic connection switching.
# The `database_selector` hash is used to pass options to the DatabaseSelector
# middleware. The `delay` is used to determine how long to wait after a write
# to send a subsequent read to the primary.
#
# The `database_resolver` class is used by the middleware to determine which
# database is appropriate to use based on the time delay.
#
# The `database_resolver_context` class is used by the middleware to set
# timestamps for the last write to the primary. The resolver uses the context
# class timestamps to determine how long to wait before reading from the
# replica.
#
# By default Rails will store a last write timestamp in the session. The
# DatabaseSelector middleware is designed as such you can define your own
# strategy for connection switching and pass that into the middleware through
# these configuration options.
config.active_record.database_selector = { delay: 2.seconds }
config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
Rails.application.routes.default_url_options = { host: ENV['FRONTEND_URL'] }
end