Skip to content

Commit

Permalink
Support process.action_mailbox (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
yykamei authored Jun 27, 2024
1 parent 7867ad3 commit f5e2f2a
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ These are Rails Instrumentation API hooks supported by this gem so far.

| Event name | Supported |
| ------------------------------------------------------------------------------------------------------------------------- | --------- |
| [`process.action_mailbox`](https://edgeguides.rubyonrails.org/active_support_instrumentation.html#process-action-mailbox) | |
| [`process.action_mailbox`](https://edgeguides.rubyonrails.org/active_support_instrumentation.html#process-action-mailbox) | |

### Railties

Expand Down
5 changes: 5 additions & 0 deletions lib/rails_band.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,9 @@ module ActionCable
module ActiveStorage
autoload :LogSubscriber, 'rails_band/active_storage/log_subscriber'
end

# RailsBand::ActionMailbox is responsible for subscribing notifications from ActionMailbox.
module ActionMailbox
autoload :LogSubscriber, 'rails_band/action_mailbox/log_subscriber'
end
end
18 changes: 18 additions & 0 deletions lib/rails_band/action_mailbox/event/process.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module RailsBand
module ActionMailbox
module Event
# A wrapper for the event that is passed to `process.action_mailbox`.
class Process < BaseEvent
def mailbox
@mailbox ||= @event.payload.fetch(:mailbox)
end

def inbound_email
@inbound_email ||= @event.payload.fetch(:inbound_email)
end
end
end
end
end
22 changes: 22 additions & 0 deletions lib/rails_band/action_mailbox/log_subscriber.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require 'rails_band/action_mailbox/event/process'

module RailsBand
module ActionMailbox
# The custom LogSubscriber for ActionMailbox.
class LogSubscriber < ::ActiveSupport::LogSubscriber
mattr_accessor :consumers

def process(event)
consumer_of(__method__)&.call(Event::Process.new(event))
end

private

def consumer_of(sub_event)
consumers[:"#{sub_event}.action_mailbox"] || consumers[:action_mailbox] || consumers[:default]
end
end
end
end
5 changes: 5 additions & 0 deletions lib/rails_band/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ class Railtie < ::Rails::Railtie
swap.call(::ActiveJob::LogSubscriber, RailsBand::ActiveJob::LogSubscriber, :active_job)
end
end

if defined?(::ActionMailbox)
RailsBand::ActionMailbox::LogSubscriber.consumers = consumers
RailsBand::ActionMailbox::LogSubscriber.attach_to :action_mailbox
end
end
end
end
9 changes: 9 additions & 0 deletions test/dummy/app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,15 @@ def message_serializer_fallback
redirect_to users_path
end

def mailbox
ActiveSupport::Notifications.instrument('process.action_mailbox',
{ mailbox: Object.new,
inbound_email: { id: 3, message_id: 'mid', status: 'processing' } }) do
# noop
end
redirect_to users_path
end

private

def halt!
Expand Down
1 change: 1 addition & 0 deletions test/dummy/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
get :cache4
get :deprecation
get :message_serializer_fallback
get :mailbox
end

resources :yay, only: %i[index show]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# frozen_string_literal: true

require 'test_helper'

class ActionMailboxProcessTest < ActionDispatch::IntegrationTest
setup do
@event = nil
RailsBand::ActionMailbox::LogSubscriber.consumers = {
'process.action_mailbox': ->(event) { @event = event }
}
@user = User.create!(name: 'foo', email: '[email protected]')
end

test 'returns name' do
get "/users/#{@user.id}/mailbox"

assert_equal 'process.action_mailbox', @event.name
end

test 'returns time' do
get "/users/#{@user.id}/mailbox"

assert_instance_of Float, @event.time
end

test 'returns end' do
get "/users/#{@user.id}/mailbox"

assert_instance_of Float, @event.end
end

test 'returns transaction_id' do
get "/users/#{@user.id}/mailbox"

assert_instance_of String, @event.transaction_id
end

test 'returns cpu_time' do
get "/users/#{@user.id}/mailbox"

assert_instance_of Float, @event.cpu_time
end

test 'returns idle_time' do
get "/users/#{@user.id}/mailbox"

assert_instance_of Float, @event.idle_time
end

test 'returns allocations' do
get "/users/#{@user.id}/mailbox"

assert_instance_of Integer, @event.allocations
end

test 'returns duration' do
get "/users/#{@user.id}/mailbox"

assert_instance_of Float, @event.duration
end

test 'calls #to_h' do
get "/users/#{@user.id}/mailbox"

%i[name time end transaction_id cpu_time idle_time allocations duration mailbox inbound_email].each do |key|
assert_includes @event.to_h, key
end
end

test 'calls #slice' do
get "/users/#{@user.id}/mailbox"

assert_equal({ name: 'process.action_mailbox' }, @event.slice(:name))
end

test 'returns an instance of Process' do
get "/users/#{@user.id}/mailbox"

assert_instance_of RailsBand::ActionMailbox::Event::Process, @event
end

test 'returns mailbox' do
get "/users/#{@user.id}/mailbox"

assert @event.mailbox
end

test 'returns inbound_email' do
get "/users/#{@user.id}/mailbox"

assert_equal({ id: 3, message_id: 'mid', status: 'processing' }, @event.inbound_email)
end
end
48 changes: 48 additions & 0 deletions test/rails_band/action_mailbox/log_subscriber_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

require 'test_helper'

class ActionMailboxLogSubscriberTest < ActionDispatch::IntegrationTest
setup do
@mock = Minitest::Mock.new
@mock.expect(:recv, nil)
@user = User.create!(name: 'bo', email: '[email protected]')
end

test 'use the consumer with the exact event name' do
RailsBand::ActionMailbox::LogSubscriber.consumers = {
'process.action_mailbox': ->(_event) { @mock.recv }
}
get "/users/#{@user.id}/mailbox"

assert_mock @mock
end

test 'use the consumer with namespace' do
RailsBand::ActionMailbox::LogSubscriber.consumers = {
action_mailbox: ->(event) { @mock.recv if event.name == 'process.action_mailbox' }
}
get "/users/#{@user.id}/mailbox"

assert_mock @mock
end

test 'use the consumer with default' do
RailsBand::ActionMailbox::LogSubscriber.consumers = {
default: ->(event) { @mock.recv if event.name == 'process.action_mailbox' }
}
get "/users/#{@user.id}/mailbox"

assert_mock @mock
end

test 'do not use the consumer because the event is not for the target' do
RailsBand::ActionMailbox::LogSubscriber.consumers = {
'unknown.action_mailbox': ->(_event) { @mock.recv }
}
get "/users/#{@user.id}/mailbox"
assert_raises MockExpectationError do
@mock.verify
end
end
end

0 comments on commit f5e2f2a

Please sign in to comment.