Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,7 @@ gem 'webpacker-react', '~> 0.3.2'
gem 'js-routes'
gem 'rollbar'
gem 'newrelic_rpm'
gem 'sidekiq'
gem 'sidekiq-failures'
gem 'sidekiq-throttled'
gem 'sidekiq-unique-jobs'
25 changes: 25 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ GEM
bindex (0.8.1)
bootsnap (1.9.1)
msgpack (~> 1.0)
brpoplpush-redis_script (0.1.2)
concurrent-ruby (~> 1.0, >= 1.0.5)
redis (>= 1.0, <= 5.0)
builder (3.2.4)
bullet (7.0.0)
activesupport (>= 3.0.0)
Expand All @@ -99,6 +102,7 @@ GEM
activesupport
childprocess (4.1.0)
concurrent-ruby (1.1.9)
connection_pool (2.2.5)
coveralls (0.7.1)
multi_json (~> 1.3)
rest-client
Expand Down Expand Up @@ -220,6 +224,8 @@ GEM
rb-fsevent (0.11.0)
rb-inotify (0.10.1)
ffi (~> 1.0)
redis (4.5.1)
redis-prescription (1.0.0)
regexp_parser (2.1.1)
responders (3.0.1)
actionpack (>= 5.0)
Expand Down Expand Up @@ -259,6 +265,21 @@ GEM
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2)
semantic_range (3.0.0)
sidekiq (6.4.0)
connection_pool (>= 2.2.2)
rack (~> 2.0)
redis (>= 4.2.0)
sidekiq-failures (1.0.1)
sidekiq (>= 4.0.0)
sidekiq-throttled (0.15.0)
concurrent-ruby
redis-prescription
sidekiq
sidekiq-unique-jobs (7.1.12)
brpoplpush-redis_script (> 0.1.1, <= 2.0.0)
concurrent-ruby (~> 1.0, >= 1.0.5)
sidekiq (>= 5.0, < 8.0)
thor (>= 0.20, < 3.0)
simple_form (5.1.0)
actionpack (>= 5.2)
activemodel (>= 5.2)
Expand Down Expand Up @@ -357,6 +378,10 @@ DEPENDENCIES
rubocop
sass-rails (>= 6)
selenium-webdriver
sidekiq
sidekiq-failures
sidekiq-throttled
sidekiq-unique-jobs
simple_form
simplecov
simplecov-lcov
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/api/v1/tasks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def create
task = current_user.my_tasks.new(task_params)

if task.save
UserMailer.with({ user: current_user, task: task }).task_created.deliver_now
SendTaskCreateNotificationJob.perform_async(task.id)
end

respond_with(task, serializer: TaskSerializer, location: nil)
Expand All @@ -29,7 +29,7 @@ def update
task = Task.find(params[:id])

if task.update(task_params)
UserMailer.with({ task: task }).task_updated.deliver_now
SendTaskUpdateNotificationJob.perform_async(task.id)
end

respond_with(task, serializer: TaskSerializer)
Expand All @@ -39,7 +39,7 @@ def destroy
task = Task.find(params[:id])

if task.destroy
UserMailer.with({ task: task }).task_destroyed.deliver_now
SendTaskDestroyNotificationJob.perform_async(task.id)
end

respond_with(task)
Expand Down
9 changes: 3 additions & 6 deletions app/jobs/application_job.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
class ApplicationJob < ActiveJob::Base
# Automatically retry jobs that encountered a deadlock
# retry_on ActiveRecord::Deadlocked

# Most jobs are safe to ignore if the underlying records are no longer available
# discard_on ActiveJob::DeserializationError
class ApplicationJob
include Sidekiq::Worker
include Sidekiq::Throttled::Worker
end
11 changes: 11 additions & 0 deletions app/jobs/send_password_reset_notification_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class SendPasswordResetNotificationJob < ApplicationJob
sidekiq_options queue: :mailers
sidekiq_throttle_as :mailer

def perform(user_id)
user = User.find_by(id: user_id)
return if user.blank?

UserMailer.with({ user: user }).reset_password.deliver_now
end
end
11 changes: 11 additions & 0 deletions app/jobs/send_task_create_notification_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class SendTaskCreateNotificationJob < ApplicationJob
sidekiq_options queue: :mailers
sidekiq_throttle_as :mailer

def perform(task_id)
task = Task.find_by(id: task_id)
return if task.blank?

UserMailer.with(user: task.author, task: task).task_created.deliver_now
end
end
11 changes: 11 additions & 0 deletions app/jobs/send_task_destroy_notification_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class SendTaskDestroyNotificationJob < ApplicationJob
sidekiq_options queue: :mailers
sidekiq_throttle_as :mailer

def perform(task_id)
task = Task.find_by(id: task_id)
return if task.blank?

UserMailer.with(user: task.author, task: task).task_destroyed.deliver_now
end
end
12 changes: 12 additions & 0 deletions app/jobs/send_task_update_notification_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class SendTaskUpdateNotificationJob < ApplicationJob
sidekiq_options queue: :mailers
sidekiq_options lock: :until_and_while_executing, on_conflict: { client: :log, server: :reject }
sidekiq_throttle_as :mailer

def perform(task_id)
task = Task.find_by(id: task_id)
return if task.blank?

UserMailer.with(user: task.author, task: task).task_updated.deliver_now
end
end
2 changes: 1 addition & 1 deletion app/services/user_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ def self.reset_password!(user)
token = SecureRandom.hex(10)
user.update!(reset_digest: token, reset_sent_at: Time.current)

UserMailer.with({ user: user }).reset_password.deliver_now
SendPasswordResetNotificationJob.perform_async(user.id)
end

def self.password_reset_period_valid?(user)
Expand Down
2 changes: 2 additions & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class Application < Rails::Application
config.load_defaults 6.1
config.assets.paths << Rails.root.join('node_modules')

config.active_job.queue_adapter = :sidekiq

# Configuration for the application, engines, and railties goes here.
#
# These settings can be overridden in specific environments using the files
Expand Down
16 changes: 16 additions & 0 deletions config/initializers/sidekiq.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require 'sidekiq/web'
require "sidekiq/throttled"
require "sidekiq/throttled/web"
require 'sidekiq_unique_jobs/web'

Sidekiq::Throttled.setup!

Sidekiq::Throttled::Registry.add(:mailer, { threshold: { limit: 1, period: 5.seconds } })

Sidekiq.configure_server do |config|
config.redis = { url: ENV['REDIS_URL'] }
end

Sidekiq.configure_client do |config|
config.redis = { url: ENV['REDIS_URL'] }
end
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Rails.application.routes.draw do
mount Sidekiq::Web => '/admin/sidekiq'
mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development?

root :to => "web/boards#show"
Expand Down
6 changes: 6 additions & 0 deletions config/sidekiq.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
:concurrency: 5
:verbose: true
:queues:
- default
- mailers
13 changes: 12 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ services:
- 3002:3002
depends_on:
- db
- redis
- sidekiq
environment: &web-environment
REDIS_URL: redis://redis
BUNDLE_PATH: /bundle_cache
GEM_HOME: /bundle_cache
GEM_PATH: /bundle_cache
Expand All @@ -24,14 +27,22 @@ services:
DATABASE_USERNAME: postgres
DATABASE_PASSWORD: postgres
command: bundle exec rails s -b '0.0.0.0' -p 3000

db:
image: postgres:11.4
ports:
- 5432:5432
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
sidekiq:
build: .
command: bundle exec sidekiq -C /task_manager/config/sidekiq.yml
environment: *web-environment
volumes: *web-volumes
depends_on:
- redis
redis:
image: redis:5.0.9-alpine

volumes:
bundle_cache:
4 changes: 2 additions & 2 deletions test/mailers/user_mailer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class UserMailerTest < ActionMailer::TestCase
email = UserMailer.with(params).task_created

assert_emails 1 do
email.deliver_now
email.deliver_later
end

assert_equal ['noreply@taskmanager.com'], email.from
Expand All @@ -25,7 +25,7 @@ class UserMailerTest < ActionMailer::TestCase
email = UserMailer.with({ user: user }).reset_password

assert_emails 1 do
email.deliver_now
email.deliver_later
end

assert_equal ['noreply@taskmanager.com'], email.from
Expand Down
3 changes: 3 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
ENV['RAILS_ENV'] ||= 'test'
require_relative '../config/environment'
require 'rails/test_help'
require 'sidekiq/testing'

Sidekiq::Testing.inline!

class ActiveSupport::TestCase
include ActionMailer::TestHelper
Expand Down