1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-04 13:05:19 +02:00

Use Redis for ActiveJob and ActionCable (#2004)

* Use Redis for ActiveJob and ActionCable

* Fix alwaysApply setting

* Update queue names and weights

* Tweak weights

* Update job queues

* Update docker setup guide

* Remove deprecated upgrade columns from users table

* Refactor Redis configuration for Sidekiq and caching in production environment

* Add Sidekiq Sentry monitoring

* queue naming fix

* Clean up schema
This commit is contained in:
Zach Gollwitzer 2025-03-19 12:36:16 -04:00 committed by GitHub
parent a7db914005
commit 19cc63c8f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
75 changed files with 328 additions and 1684 deletions

View file

@ -24,8 +24,6 @@ module Maybe
# config.time_zone = "Central Time (US & Canada)"
# config.eager_load_paths << Rails.root.join("extras")
config.active_job.queue_adapter = :good_job
# TODO: This is here for incremental adoption of localization. This can be removed when all translations are implemented.
config.i18n.fallbacks = true

View file

@ -1,8 +1,10 @@
development:
adapter: postgresql
adapter: async
test:
adapter: test
production:
adapter: postgresql
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: maybe_production

View file

@ -1 +1 @@
HMC62biPQuF61XA8tnd/kvwdV2xr/zpfJxG+IHNgGtpuvPXi9oS+YemBGMLte+1Q7elzAAbmKg73699hVLkRcBCk/FaMQjGRF2lnJ9MpxSR/br8Uma2bSH40lIEjxAfzjr4JPSfsHxlArF30hfd+B9obPDOptLQbpENPBsmiuEHX7S0Y8SmKuzDUVrvdfeLoVuMiAZqOP5izpBAbXfvMjI3YH70iJAaPlfAxQqR89O2nSt+N27siyyfkypE3NHQKZFz+Rmo8uJDlaD3eo/uvQN4xsgRCMUar4X2iY4UOd+MIGAPqLzIUhhJ56G5MRDJ4XpJA6RDuGFc/LNyxdXt0WinUX8Yz7zKiKah1NkEhTkH+b2ylFbsN6cjlqcX0yw8Gw8B4osyHQGnj7Tuf1c8k1z3gBoaQALm8zxKCaJ9k6CopVM2GmbpCLcJqjN1L71wCe6MiWsv9LDF/pwuZNG6hWn0oykdkWeBEQyK8g4Wo1AHqgEi8XtRwbaX6yugO5WQFhjQG/LzXcG02E5Co5/r/G7ZSFpRC9ngoOx3LY6MihPRkTIOumCg3HHtAsWBeHe4L/rDIe4A=--hlLxVbnyuYXf7Rku--A6Cwdr3CAW6bRkl1rcRmRw==
Be5nAlhacgJFHZJBgO8noswyX/VOrmkMem7wS3YQhoogzG0MCSVxCAVMbFyYFYUwqZrSPkAqUTpgH5OJJ1FB1gZfL9IYYWnEdTzMxM7IvhdDwYllYcM6smbvZEbOiqxLs9VdfC/qFS+1iFtsezBaqxfGdANJsJt3TxoRWl/ZbQ4Od1s0BNkMis1CDZt5RMEQlTz813cE5sXBlxhqEr9/2CaktwPIe5S/Oxrwo8vPFBvrNdox8BysiK9WDik8jJFSVwPSCvg43/MaIJUT0cOILdSxqrATXV143/h6ghNYtrJgoUNFT7wuu0FTU/ovTgtTqQEKG+7PDO1WLFn606bVknjPwfNMGBa9hX3LbRErDDIXNq69um9fPZ8Yq5f9jP++dPbAqbWBEg+JYsZmDgzr7LmtXVzQgAcuMkHaBbL8uxod8S1B6qhXhLNc8Dd1oeHVu0kcLFO2zaqdYRFNEY30JSjjXlG3GExXQE6aEluXvdF2gj9Hjhp7tEXZEJbIx+ZFy+6Xbrd1E2BE8AZUbalExAfudkPSYlAZ+z3fWc2RlNIuBzTYDOWH9Ai8mqsdyGNVEyizXQ==--j/6QtlLtP4mYXIFw--c+AKfDPo9stantWni+u+4Q==

View file

@ -1,22 +1,7 @@
default: &default
adapter: postgresql
encoding: unicode
# Note on DB_POOL_SIZE:
# -------------------------------------------------------------------------------------------------------------
# To optimize for the simplest self-hosting setup, we run ActionCable, GoodJob, and Rails in the same process.
#
# This requires DB connections for each:
#
# Puma: Requires 3 connections (Rails default)
# ActionCable: 5 connections (Rails defaults to 4 workers + 1 listener for Postgres adapter)
# GoodJob: 15 connections to run in "async" mode. See `good_job.rb` for the breakdown.
# --------------------------------------------------------------------------------------------
# Total: 23 connections
#
# We default to this value so that self-hosters don't need to configure anything. Hosted mode will require
# a different pool size, as we run ActionCable, GoodJob, and Rails in separate processes.
#
pool: <%= ENV.fetch("DB_POOL_SIZE") { 23 } %>
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 3 } %>
host: <%= ENV.fetch("DB_HOST") { "127.0.0.1" } %>
port: <%= ENV.fetch("DB_PORT") { "5432" } %>
user: <%= ENV.fetch("POSTGRES_USER") { nil } %>

View file

@ -69,11 +69,12 @@ Rails.application.configure do
# want to log everything, set the level to "debug".
config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info")
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
if ENV["CACHE_REDIS_URL"].present?
config.cache_store = :redis_cache_store, { url: ENV["CACHE_REDIS_URL"] }
end
config.action_mailer.perform_caching = false
config.action_mailer.deliver_later_queue_name = :high_priority
config.action_mailer.default_url_options = { host: ENV["APP_DOMAIN"] }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
@ -105,4 +106,7 @@ Rails.application.configure do
# ]
# Skip DNS rebinding protection for the default health check endpoint.
# config.host_authorization = { exclude: ->(request) { request.path == "/up" } }
# set REDIS_URL for Sidekiq to use Redis
config.active_job.queue_adapter = :sidekiq
end

View file

@ -1,33 +0,0 @@
Rails.application.configure do
config.good_job.enable_cron = true
if ENV["UPGRADES_ENABLED"] == "true"
config.good_job.cron = {
auto_upgrade: {
cron: "every 2 minutes",
class: "AutoUpgradeJob",
description: "Check for new versions of the app and upgrade if necessary"
}
}
end
config.good_job.on_thread_error = ->(exception) { Rails.error.report(exception) }
# 7 dedicated queue threads + 5 catch-all threads + 3 for job listener, cron, executor = 15 threads allocated
# `latency_low` queue for jobs ~30s
# `latency_medium` queue for jobs ~1-2 min
# `latency_high` queue for jobs ~5+ min
config.good_job.queues = "latency_low:2;latency_low,latency_medium:3;latency_low,latency_medium,latency_high:2;*"
# Auth for jobs admin dashboard
ActiveSupport.on_load(:good_job_application_controller) do
before_action do
raise ActionController::RoutingError.new("Not Found") unless current_user&.super_admin? || Rails.env.development?
end
def current_user
session = Session.find_by(id: cookies.signed[:session_token])
session&.user
end
end
end

View file

@ -0,0 +1,9 @@
require "sidekiq/web"
Sidekiq::Web.use(Rack::Auth::Basic) do |username, password|
configured_username = ::Digest::SHA256.hexdigest(ENV.fetch("SIDEKIQ_WEB_USERNAME", "maybe"))
configured_password = ::Digest::SHA256.hexdigest(ENV.fetch("SIDEKIQ_WEB_PASSWORD", "maybe"))
ActiveSupport::SecurityUtils.secure_compare(::Digest::SHA256.hexdigest(username), configured_username) &&
ActiveSupport::SecurityUtils.secure_compare(::Digest::SHA256.hexdigest(password), configured_password)
end

View file

@ -1,13 +0,0 @@
---
en:
upgrader:
deployer:
null_deployer:
success_message: 'No-op: null deployer initiated deploy successfully'
render:
deploy_log_error: 'Failed to deploy %{type} %{commit_sha} to Render: %{error_message}'
deploy_log_info: Deploying %{type} %{commit_sha} to Render...
error_message_failed_deploy: Failed to deploy to Render
error_message_not_set: Render deploy hook URL is not set
success_message: 'Triggered deployment to Render for commit: %{commit_sha}'
troubleshooting_url: https://render.com/docs/deploy-hooks

View file

@ -11,11 +11,6 @@ en:
generate_tokens: Generate new code
generated_tokens: Generated codes
title: Require invite code for signup
provider_settings:
description: Configure settings for your hosting provider
render_deploy_hook_label: Render Deploy Hook URL
render_deploy_hook_placeholder: https://api.render.com/deploy/srv-xyz...
title: Provider Settings
show:
general: General Settings
invites: Invite Codes
@ -38,14 +33,4 @@ en:
success: Settings updated
clear_cache:
cache_cleared: Data cache has been cleared. This may take a few moments to complete.
upgrade_settings:
description: Configure how your application receives updates
latest_commit_description: Automatically update to the latest commit (unstable)
latest_commit_title: Latest Commit
latest_release_description: Automatically update to the most recent release
(stable)
latest_release_title: Latest Release
manual_description: You control when to download and install updates
manual_title: Manual
title: Auto Upgrade
not_authorized: You are not authorized to perform this action

View file

@ -10,8 +10,3 @@ en:
label: Amount
syncing_notice:
syncing: Syncing accounts data...
upgrade_notification:
app_upgraded: The app has been upgraded to %{version}.
dismiss: Dismiss
new_version_available: A new version of Maybe is available for upgrade.
upgrade_now: Upgrade Now

View file

@ -1,10 +0,0 @@
---
en:
upgrades:
acknowledge:
upgrade_complete_dismiss: We hope you enjoy the new features!
upgrade_dismissed: Upgrade dismissed
upgrade_not_available: Upgrade not available
upgrade_not_found: Upgrade not found
deploy:
upgrade_not_found: Upgrade not found

View file

@ -1,3 +1,5 @@
require "sidekiq/web"
Rails.application.routes.draw do
# MFA routes
resource :mfa, controller: "mfa", only: [ :new, :create ] do
@ -6,7 +8,8 @@ Rails.application.routes.draw do
delete :disable
end
mount GoodJob::Engine => "good_job"
# Uses basic auth - see config/initializers/sidekiq.rb
mount Sidekiq::Web => "/sidekiq"
get "changelog", to: "pages#changelog"
get "feedback", to: "pages#feedback"
@ -158,14 +161,6 @@ Rails.application.routes.draw do
get :accept, on: :member
end
# For managing self-hosted upgrades and release notifications
resources :upgrades, only: [] do
member do
post :acknowledge
post :deploy
end
end
resources :currencies, only: %i[show]
resources :impersonation_sessions, only: [ :create ] do

5
config/sidekiq.yml Normal file
View file

@ -0,0 +1,5 @@
concurrency: <%= ENV.fetch("RAILS_MAX_THREADS") { 3 } %>
queues:
- [high_priority, 7]
- [medium_priority, 2]
- [low_priority, 1]

View file

@ -22,16 +22,4 @@ cloudflare:
bucket: <%= ENV['CLOUDFLARE_BUCKET'] %>
request_checksum_calculation: "when_required"
response_checksum_validation: "when_required"
# Removed in #702. Uncomment, add gems, update .env.example to enable.
#google:
# service: GCS
# project: <%#= ENV["GCS_PROJECT"] %>
# credentials: <%#= Rails.root.join("gcp-storage-keyfile.json") %>
# bucket: <%#= ENV["GCS_BUCKET"] %>
#azure:
# service: AzureStorage
# storage_account_name: <%#= ENV["AZURE_STORAGE_ACCOUNT_NAME"] %>
# storage_access_key: <%#= ENV["AZURE_STORAGE_ACCESS_KEY"] %>
# container: <%#= ENV["AZURE_STORAGE_CONTAINER"] %>