Class: BabySMS::MailMan

Inherits:
Object
  • Object
show all
Defined in:
lib/babysms/mail_man.rb

Overview

MailMan is the link between a Message and an Adapter. It basically has a strategy for choosing adapters, and attempting delivery until either the message is delivered, or all adapters have been tried.

The boring strategy is :in_order, which is good for cases where you have a primary adapter, and one or more fallbacks.

The alternative is :random, which sort of works in a load-balancing kind of way.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(adapters:, strategy:) ⇒ MailMan

Returns a new instance of MailMan.



16
17
18
19
20
21
22
23
# File 'lib/babysms/mail_man.rb', line 16

def initialize(adapters:, strategy:)
  unless respond_to?(:"next_#{strategy}_adapter", true)
    fail ArgumentError, "invalid strategy: #{strategy.inspect}"
  end

  @adapters = adapters.dup
  @strategy = strategy
end

Instance Attribute Details

#adaptersObject (readonly)

Returns the value of attribute adapters.



13
14
15
# File 'lib/babysms/mail_man.rb', line 13

def adapters
  @adapters
end

#strategyObject (readonly)

Returns the value of attribute strategy.



14
15
16
# File 'lib/babysms/mail_man.rb', line 14

def strategy
  @strategy
end

Instance Method Details

#deliver(message) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/babysms/mail_man.rb', line 25

def deliver(message)
  # If the message has a "from", we need to use that adapter, even if
  # others are available
  if message.from
    specified = BabySMS::Adapter.for_number(message.from, pool: adapters)

    if specified.nil?
      fail BabySMS::Error, "`from:' not associated with an adapter: #{message.from}"
    end
    @adapters = [specified]
  end

  if @adapters.empty?
    fail BabySMS::Error, 'no adapter configured'
  end

  # We collect and return all errors leading up to the (hopefully) successful delivery
  failures = []
  each_adapter do |adapter|
    return BabySMS::Receipt.new(message_uuid: adapter.deliver(self),
                                message: message,
                                adapter: adapter,
                                exceptions: failures)
  rescue BabySMS::FailedDelivery => e
    failures.push(e)
  end

  raise BabySMS::FailedDelivery.multiple(failures)
end