toiler 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'toiler/actor/fetcher'
2
4
  require 'toiler/actor/processor'
3
5
 
@@ -7,10 +9,9 @@ module Toiler
7
9
  class Supervisor < Concurrent::Actor::RestartingContext
8
10
  include Utils::ActorLogging
9
11
 
10
- attr_accessor :client
11
-
12
12
  def initialize
13
- @client = ::Aws::SQS::Client.new
13
+ super
14
+
14
15
  spawn_processors
15
16
  spawn_fetchers
16
17
  end
@@ -21,11 +22,12 @@ module Toiler
21
22
 
22
23
  def spawn_fetchers
23
24
  Toiler.active_worker_class_registry.each do |queue, klass|
24
- count = klass.concurrency
25
+ count = klass.concurrency
26
+ provider = klass.provider
25
27
  begin
26
28
  fetcher = Actor::Fetcher.spawn! name: "fetcher_#{queue}".to_sym,
27
29
  supervise: true,
28
- args: [queue, client, count]
30
+ args: [queue, count, provider]
29
31
  Toiler.set_fetcher queue, fetcher
30
32
  rescue StandardError => e
31
33
  error "Failed to start Fetcher for queue #{queue}: #{e.message}\n#{e.backtrace.join("\n")}"
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Toiler
2
4
  module Actor
3
5
  module Utils
4
6
  # Provides helper methods for logging
5
7
  module ActorLogging
6
8
  def error(msg)
7
- log Logger::Severity::ERROR, msg
9
+ log Logger::Severity::ERROR, msg
8
10
  end
9
11
 
10
12
  def info(msg)
@@ -12,7 +14,7 @@ module Toiler
12
14
  end
13
15
 
14
16
  def debug(msg)
15
- log Logger::Severity::DEBUG, msg
17
+ log Logger::Severity::DEBUG, msg
16
18
  end
17
19
 
18
20
  def warn(msg)
@@ -20,7 +22,7 @@ module Toiler
20
22
  end
21
23
 
22
24
  def fatal(msg)
23
- log Logger::Severity::FATAL, msg
25
+ log Logger::Severity::FATAL, msg
24
26
  end
25
27
  end
26
28
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Toiler
2
4
  module Aws
3
5
  # SQS Message abstraction
@@ -24,7 +26,7 @@ module Toiler
24
26
  )
25
27
  end
26
28
 
27
- def visibility_timeout=(timeout)
29
+ def modify_ack_deadline!(timeout)
28
30
  client.change_message_visibility(
29
31
  queue_url: queue_url,
30
32
  receipt_handle: data.receipt_handle,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'toiler/aws/message'
2
4
 
3
5
  module Toiler
@@ -7,13 +9,13 @@ module Toiler
7
9
  class Queue
8
10
  attr_accessor :name, :client, :url
9
11
 
10
- def initialize(name, client = nil)
12
+ def initialize(name, client)
11
13
  @name = name
12
- @client = client || ::Aws::SQS::Client.new
14
+ @client = client
13
15
  @url = client.get_queue_url(queue_name: name).queue_url
14
16
  end
15
17
 
16
- def visibility_timeout
18
+ def ack_deadline
17
19
  client.get_queue_attributes(
18
20
  queue_url: url,
19
21
  attribute_names: ['VisibilityTimeout']
@@ -30,14 +32,22 @@ module Toiler
30
32
 
31
33
  def send_messages(options)
32
34
  client.send_message_batch(
33
- sanitize_message_body options.merge queue_url: url
35
+ sanitize_message_body(options.merge(queue_url: url))
34
36
  )
35
37
  end
36
38
 
37
- def receive_messages(options)
38
- client.receive_message(options.merge(queue_url: url))
39
- .messages
40
- .map { |m| Message.new(client, url, m) }
39
+ def receive_messages(wait: nil, max_messages: nil)
40
+ client.receive_message(attribute_names: %w[All],
41
+ message_attribute_names: %w[All],
42
+ wait_time_seconds: wait,
43
+ max_number_of_messages: max_messages,
44
+ queue_url: url)
45
+ .messages
46
+ .map { |m| Message.new(client, url, m) }
47
+ end
48
+
49
+ def max_messages
50
+ 10
41
51
  end
42
52
 
43
53
  private
@@ -50,7 +60,7 @@ module Toiler
50
60
  if body.is_a?(Hash)
51
61
  m[:message_body] = JSON.dump(body)
52
62
  elsif !body.is_a? String
53
- fail ArgumentError, "Body must be a String, found #{body.class}"
63
+ raise ArgumentError, "Body must be a String, found #{body.class}"
54
64
  end
55
65
  end
56
66
 
data/lib/toiler/cli.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'singleton'
2
4
  require 'timeout'
3
5
  require 'optparse'
@@ -7,6 +9,7 @@ module Toiler
7
9
  # See: https://github.com/mperham/sidekiq/blob/33f5d6b2b6c0dfaab11e5d39688cab7ebadc83ae/lib/sidekiq/cli.rb#L20
8
10
  class Shutdown < Interrupt; end
9
11
 
12
+ # WaitShutdown is used to handle graceful shutdowns
10
13
  class WaitShutdown < Interrupt
11
14
  attr_accessor :wait
12
15
 
@@ -39,12 +42,12 @@ module Toiler
39
42
  private
40
43
 
41
44
  def handle_stop
42
- while (readable_io = IO.select([@self_read]))
45
+ while (readable_io = @self_read.wait_readable)
43
46
  handle_signal(readable_io.first[0].gets.strip)
44
47
  end
45
- rescue WaitShutdown => shutdown_error
46
- Toiler.logger.info "Received Interrupt, Waiting up to #{shutdown_error.wait} seconds for actors to finish..."
47
- success = supervisor.ask(:terminate!).wait(shutdown_error.wait)
48
+ rescue WaitShutdown => e
49
+ Toiler.logger.info "Received Interrupt, Waiting up to #{e.wait} seconds for actors to finish..."
50
+ success = supervisor.ask(:terminate!).wait(e.wait)
48
51
  if success
49
52
  Toiler.logger.info 'Supervisor successfully terminated'
50
53
  else
@@ -58,6 +61,7 @@ module Toiler
58
61
  Concurrent.global_fast_executor.shutdown
59
62
  Concurrent.global_io_executor.shutdown
60
63
  return if Concurrent.global_io_executor.wait_for_termination(60)
64
+
61
65
  Concurrent.global_io_executor.kill
62
66
  end
63
67
 
@@ -67,21 +71,20 @@ module Toiler
67
71
  end
68
72
 
69
73
  def trap_signals
70
- %w(INT TERM QUIT USR1 USR2 TTIN ABRT).each do |sig|
71
- begin
72
- trap sig do
73
- @self_write.puts(sig)
74
- end
75
- rescue ArgumentError
76
- puts "System does not support signal #{sig}"
74
+ %w[INT TERM QUIT USR1 USR2 TTIN ABRT].each do |sig|
75
+ trap sig do
76
+ @self_write.puts(sig)
77
77
  end
78
+ rescue ArgumentError
79
+ puts "System does not support signal #{sig}"
78
80
  end
79
81
  end
80
82
 
81
83
  def print_stacktraces
82
84
  return unless Toiler.logger
83
- Toiler.logger.info "-------------------"
84
- Toiler.logger.info "Received QUIT, dumping threads:"
85
+
86
+ Toiler.logger.info '-------------------'
87
+ Toiler.logger.info 'Received QUIT, dumping threads:'
85
88
  Thread.list.each do |t|
86
89
  id = t.object_id
87
90
  Toiler.logger.info "[thread:#{id}] #{t.backtrace.join("\n[thread:#{id}] ")}"
@@ -91,21 +94,24 @@ module Toiler
91
94
 
92
95
  def print_status
93
96
  return unless Toiler.logger
94
- Toiler.logger.info "-------------------"
95
- Toiler.logger.info "Received QUIT, dumping status:"
97
+
98
+ Toiler.logger.info '-------------------'
99
+ Toiler.logger.info 'Received QUIT, dumping status:'
96
100
  Toiler.queues.each do |queue|
97
101
  fetcher = Toiler.fetcher(queue).send(:core).send(:context)
98
102
  processor_pool = Toiler.processor_pool(queue).send(:core).send(:context)
99
- processors = processor_pool.instance_variable_get(:@workers).collect{|w| w.send(:core).send(:context)}
100
- busy_processors = processors.count{|pr| pr.executing?}
103
+ processors = processor_pool.instance_variable_get(:@workers).collect { |w| w.send(:core).send(:context) }
104
+ busy_processors = processors.count(&:executing?)
101
105
  message = "Status for [queue:#{queue}]:"
102
- message += "\n[fetcher:#{fetcher.name}] [executing:#{fetcher.executing?}] [waiting_messages:#{fetcher.waiting_messages}] [free_processors:#{fetcher.free_processors}]"
106
+ message += "\n[fetcher:#{fetcher.name}] [executing:#{fetcher.executing?}] " \
107
+ "[waiting_messages:#{fetcher.waiting_messages}] [free_processors:#{fetcher.free_processors}] " \
108
+ "[scheduled_task:#{!fetcher.scheduled_task.nil?}]"
103
109
  message += "\n[processor_pool:#{processor_pool.name}] [workers:#{processors.count}] [busy:#{busy_processors}]"
104
110
  processors.each do |processor|
105
111
  thread = processor.thread
106
- thread_id = thread.nil? ? "nil" : thread.object_id
112
+ thread_id = thread.nil? ? 'nil' : thread.object_id
107
113
  message += "\n[processor:#{processor.name}] [executing:#{processor.executing?}] [thread:#{thread_id}]"
108
- message += " Stack:\n" + thread.backtrace.join("\n\t") unless thread.nil?
114
+ message += " Stack:\n#{thread.backtrace.join("\n\t")}" unless thread.nil?
109
115
  end
110
116
  Toiler.logger.info message
111
117
  end
@@ -118,22 +124,24 @@ module Toiler
118
124
  print_stacktraces
119
125
  print_status
120
126
  when 'INT', 'TERM'
121
- fail WaitShutdown, 60
127
+ raise WaitShutdown, 60
122
128
  when 'ABRT'
123
- fail WaitShutdown, Toiler.options[:shutdown_timeout] * 60
129
+ raise WaitShutdown, Toiler.options[:shutdown_timeout] * 60
124
130
  end
125
131
  end
126
132
 
127
133
  def load_concurrent
128
134
  require 'concurrent-edge'
129
- Concurrent.global_logger = lambda do |level, progname, msg = nil, &block|
130
- Toiler.logger.log(level, msg, progname, &block)
131
- end if Toiler.logger
135
+ if Toiler.logger
136
+ Concurrent.global_logger = lambda do |level, progname, msg = nil, &block|
137
+ Toiler.logger.log(level, msg, progname, &block)
138
+ end
139
+ end
132
140
  end
133
141
 
134
142
  def daemonize
135
143
  return unless Toiler.options[:daemon]
136
- fail 'Logfile required when daemonizing' unless Toiler.options[:logfile]
144
+ raise 'Logfile required when daemonizing' unless Toiler.options[:logfile]
137
145
 
138
146
  files_to_reopen = []
139
147
  ObjectSpace.each_object(File) do |file|
@@ -148,12 +156,10 @@ module Toiler
148
156
 
149
157
  def reopen_files(files_to_reopen)
150
158
  files_to_reopen.each do |file|
151
- begin
152
- file.reopen file.path, 'a+'
153
- file.sync = true
154
- rescue StandardError
155
- puts "Failed to reopen file #{file}"
156
- end
159
+ file.reopen file.path, 'a+'
160
+ file.sync = true
161
+ rescue StandardError
162
+ puts "Failed to reopen file #{file}"
157
163
  end
158
164
  end
159
165
 
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Toiler
4
+ module Gcp
5
+ # PubSub Message abstraction
6
+ # Provides methods for querying and acting on a PubSub message
7
+ class Message
8
+ attr_accessor :message
9
+
10
+ def initialize(message)
11
+ @message = message
12
+ end
13
+
14
+ def delete
15
+ message.acknowledge!
16
+ end
17
+
18
+ def modify_ack_deadline!(timeout)
19
+ message.modify_ack_deadline! timeout
20
+ end
21
+
22
+ def message_id
23
+ message.message_id
24
+ end
25
+
26
+ def body
27
+ message.data
28
+ end
29
+
30
+ def attributes
31
+ message.attributes
32
+ end
33
+
34
+ def delivery_attempt
35
+ message.delivery_attempt
36
+ end
37
+
38
+ def ordering_key
39
+ message.ordering_key
40
+ end
41
+
42
+ def reject!
43
+ message.reject!
44
+ end
45
+
46
+ def published_at
47
+ message.published_at
48
+ end
49
+
50
+ def ack_id
51
+ message.ack_id
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'toiler/gcp/message'
4
+
5
+ module Toiler
6
+ module Gcp
7
+ # GCP PubSub Queue abstraction
8
+ # Provides methods for querying and acting on a PubSub queue
9
+ class Queue
10
+ attr_accessor :name, :subscription
11
+
12
+ def initialize(name, client)
13
+ @name = name
14
+ @subscription = client.subscription name, skip_lookup: true
15
+ end
16
+
17
+ def ack_deadline
18
+ subscription.deadline
19
+ end
20
+
21
+ def delete_messages(messages)
22
+ subscription.acknowledge(messages)
23
+ end
24
+
25
+ def max_messages
26
+ # pubsub limit is 1000, but it makes little sense to pull so many messages at once
27
+ 100
28
+ end
29
+
30
+ def receive_messages(wait: nil, max_messages: nil)
31
+ immediate = wait.nil? || wait.zero?
32
+ subscription.pull(immediate: immediate, max: max_messages)
33
+ .map { |m| Message.new(m) }
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Toiler
2
4
  module Utils
3
5
  # Parses command-line arguments
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'erb'
2
4
  require 'yaml'
3
5
 
@@ -12,7 +14,7 @@ module Toiler
12
14
  end
13
15
 
14
16
  def self.load_for_rails_console
15
- load(config_file: (Rails.root + 'config' + 'toiler.yml'))
17
+ load(config_file: "#{Rails.root}configtoiler.yml")
16
18
  end
17
19
 
18
20
  def initialize(options)
@@ -26,36 +28,32 @@ module Toiler
26
28
  Toiler.options.merge!(config_file_options)
27
29
  Toiler.options.merge!(options)
28
30
  initialize_aws
31
+ initialize_gcp
29
32
  end
30
33
 
31
34
  private
32
35
 
33
36
  def config_file_options
34
- if (path = options[:config_file])
35
- unless File.exist?(path)
36
- Toiler.logger.warn "Config file #{path} does not exist"
37
- path = nil
38
- end
37
+ if (path = options[:config_file]) && !File.exist?(path)
38
+ Toiler.logger.warn "Config file #{path} does not exist"
39
+ path = nil
39
40
  end
40
41
 
41
42
  return {} unless path
42
43
 
43
- deep_symbolize_keys YAML.load(ERB.new(File.read(path)).result)
44
+ deep_symbolize_keys YAML.safe_load(ERB.new(File.read(path)).result)
44
45
  end
45
46
 
46
47
  def initialize_aws
47
48
  return if Toiler.options[:aws].empty?
48
- ::Aws.config[:region] = Toiler.options[:aws][:region]
49
- ::Aws.config[:endpoint] = Toiler.options[:aws][:endpoint] if Toiler.options[:aws][:endpoint]
50
- set_aws_credentials
49
+
50
+ Toiler.aws_client = ::Aws::SQS::Client.new Toiler.options[:aws]
51
51
  end
52
52
 
53
- def set_aws_credentials
54
- return unless Toiler.options[:aws][:access_key_id]
55
- ::Aws.config[:credentials] = ::Aws::Credentials.new(
56
- Toiler.options[:aws][:access_key_id],
57
- Toiler.options[:aws][:secret_access_key]
58
- )
53
+ def initialize_gcp
54
+ return if Toiler.options[:gcp].empty?
55
+
56
+ Toiler.gcp_client = ::Google::Cloud::PubSub.new Toiler.options[:gcp]
59
57
  end
60
58
 
61
59
  def initialize_logger
@@ -90,8 +88,8 @@ module Toiler
90
88
  require options[:require]
91
89
  end
92
90
 
93
- def deep_symbolize_keys(h)
94
- h.each_with_object({}) do |(key, value), result|
91
+ def deep_symbolize_keys(hash)
92
+ hash.each_with_object({}) do |(key, value), result|
95
93
  k = key.respond_to?(:to_sym) ? key.to_sym : key
96
94
  result[k] = if value.is_a? Hash
97
95
  deep_symbolize_keys value
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'time'
2
4
  require 'logger'
3
5
 
@@ -21,8 +23,8 @@ module Toiler
21
23
 
22
24
  module_function
23
25
 
24
- def initialize_logger(log_target = STDOUT)
25
- log_target = STDOUT if log_target.nil?
26
+ def initialize_logger(log_target = $stdout)
27
+ log_target = $stdout if log_target.nil?
26
28
  @logger = Logger.new(log_target)
27
29
  @logger.level = Logger::INFO
28
30
  @logger.formatter = Pretty.new
@@ -34,7 +36,7 @@ module Toiler
34
36
  end
35
37
 
36
38
  def logger=(log)
37
- @logger = (log ? log : Logger.new('/dev/null'))
39
+ @logger = (log || Logger.new('/dev/null'))
38
40
  end
39
41
  end
40
42
  end
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Toiler Version
2
4
  module Toiler
3
- VERSION = '0.6.1'.freeze
5
+ VERSION = '0.7.0'
4
6
  end
data/lib/toiler/worker.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Toiler
2
4
  # Toiler's Worker behaviour
3
5
  module Worker
@@ -34,26 +36,32 @@ module Toiler
34
36
  module ClassMethods
35
37
  def toiler_options(options = {})
36
38
  return class_variable_get(:@@toiler_options) if options.empty?
39
+
37
40
  Toiler.register_worker(options[:queue], self) if options[:queue]
38
41
  class_variable_get(:@@toiler_options).merge! options
39
42
  end
40
43
 
41
- def batch?
42
- class_variable_get(:@@toiler_options)[:batch]
43
- end
44
-
45
44
  def concurrency
46
45
  class_variable_get(:@@toiler_options)[:concurrency]
47
46
  end
48
47
 
48
+ def provider
49
+ class_variable_get(:@@toiler_options)[:provider]
50
+ end
51
+
49
52
  def queue
50
53
  class_variable_get(:@@toiler_options)[:queue]
51
54
  end
52
55
 
56
+ # kept for compatibility reasons
53
57
  def auto_visibility_timeout?
54
58
  class_variable_get(:@@toiler_options)[:auto_visibility_timeout]
55
59
  end
56
60
 
61
+ def deadline_extension?
62
+ class_variable_get(:@@toiler_options)[:deadline_extension]
63
+ end
64
+
57
65
  def auto_delete?
58
66
  class_variable_get(:@@toiler_options)[:auto_delete]
59
67
  end
data/lib/toiler.rb CHANGED
@@ -1,4 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'aws-sdk-sqs'
4
+ require 'google/cloud/pubsub'
5
+ require 'grpc'
2
6
  require 'toiler/utils/environment_loader'
3
7
  require 'toiler/utils/logging'
4
8
  require 'toiler/utils/argument_parser'
@@ -10,13 +14,19 @@ require 'toiler/version'
10
14
  module Toiler
11
15
  @worker_class_registry = {}
12
16
  @options = {
13
- aws: {}
17
+ aws: {},
18
+ gcp: {}
14
19
  }
15
20
  @fetchers = {}
16
21
  @processor_pools = {}
22
+ @aws_client = nil
23
+ @gcp_client = nil
17
24
 
18
25
  attr_reader :worker_class_registry, :options, :fetchers, :processor_pools
19
- module_function :worker_class_registry, :options, :fetchers, :processor_pools
26
+ attr_accessor :aws_client, :gcp_client
27
+
28
+ module_function :worker_class_registry, :options, :fetchers, :processor_pools,
29
+ :aws_client, :gcp_client, :aws_client=, :gcp_client=
20
30
 
21
31
  module_function
22
32
 
@@ -63,10 +73,10 @@ module Toiler
63
73
  def default_options
64
74
  {
65
75
  auto_visibility_timeout: false,
76
+ deadline_extension: false,
66
77
  concurrency: 1,
67
78
  auto_delete: false,
68
- shutdown_timeout: 5,
69
- batch: false
79
+ shutdown_timeout: 5
70
80
  }
71
81
  end
72
82
 
@@ -4,19 +4,45 @@ require 'toiler/actor/fetcher'
4
4
  RSpec.describe Toiler::Actor::Fetcher, type: :model do
5
5
  let(:queue) { 'default' }
6
6
  let(:client) { double(:aws_sqs_client) }
7
+ let(:aws_queue) { double(:aws_queue) }
8
+ let(:gcp_queue) { double(:gcp_queue) }
7
9
 
8
10
  before do
9
11
  allow_any_instance_of(Toiler::Actor::Fetcher).to receive(:log).and_return(true)
10
12
  allow_any_instance_of(Toiler::Actor::Fetcher).to receive(:tell)
11
- allow_any_instance_of(Toiler::Aws::Queue).to receive(:visibility_timeout).and_return(100)
13
+ allow(Toiler::Aws::Queue).to receive(:new).and_return(aws_queue)
14
+ allow(Toiler::Gcp::Queue).to receive(:new).and_return(gcp_queue)
15
+ allow(aws_queue).to receive(:ack_deadline).and_return(100)
16
+ allow(gcp_queue).to receive(:ack_deadline).and_return(100)
12
17
  allow(client).to receive(:get_queue_url).with(queue_name: 'default').and_return double(:queue, queue_url: 'http://aws.fake/queue')
13
18
  end
14
19
 
15
20
  describe "#new" do
16
- it 'completes sucessfully' do
17
- fetcher = described_class.new(queue, client, 1)
18
- expect(fetcher).to have_received(:tell).with(:poll_messages)
19
- expect(fetcher.executing?).to eq(false)
21
+ context 'default' do
22
+ it 'completes sucessfully' do
23
+ fetcher = described_class.new(queue, 1, nil)
24
+ expect(aws_queue).to have_received(:ack_deadline)
25
+ expect(fetcher).to have_received(:tell).with(:pull_messages)
26
+ expect(fetcher.executing?).to eq(false)
27
+ end
28
+ end
29
+
30
+ context 'aws' do
31
+ it 'completes sucessfully' do
32
+ fetcher = described_class.new(queue, 1, :aws)
33
+ expect(aws_queue).to have_received(:ack_deadline)
34
+ expect(fetcher).to have_received(:tell).with(:pull_messages)
35
+ expect(fetcher.executing?).to eq(false)
36
+ end
37
+ end
38
+
39
+ context 'gcp' do
40
+ it 'completes sucessfully' do
41
+ fetcher = described_class.new(queue, 1, :gcp)
42
+ expect(gcp_queue).to have_received(:ack_deadline)
43
+ expect(fetcher).to have_received(:tell).with(:pull_messages)
44
+ expect(fetcher.executing?).to eq(false)
45
+ end
20
46
  end
21
47
  end
22
48
  end
@@ -2,7 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  require 'toiler/actor/supervisor'
4
4
  RSpec.describe Toiler::Actor::Supervisor, type: :model do
5
- let(:sqs_client) { double(:client) }
6
5
  describe "#new" do
7
6
  it 'only spawns fetchers for active workers' do
8
7
  class InactiveWorker
@@ -12,8 +11,7 @@ RSpec.describe Toiler::Actor::Supervisor, type: :model do
12
11
  end
13
12
 
14
13
  Toiler.options.merge!(active_queues: ['default'])
15
- expect(::Aws::SQS::Client).to receive(:new).and_return(sqs_client)
16
- expect(Toiler::Actor::Fetcher).to receive(:spawn!).with(name: :fetcher_default, supervise: true, args: ['default', sqs_client, 1])
14
+ expect(Toiler::Actor::Fetcher).to receive(:spawn!).with(name: :fetcher_default, supervise: true, args: ['default', 1, nil])
17
15
  expect(Concurrent::Actor::Utils::Pool).to receive(:spawn!).with(:processor_pool_default, 1)
18
16
  supervisor = described_class.new
19
17
  end
@@ -23,5 +21,18 @@ RSpec.describe Toiler::Actor::Supervisor, type: :model do
23
21
  expect(Toiler::Utils::Logging.logger).to receive(:warn).with("No worker assigned to queue: missing")
24
22
  Toiler.active_worker_class_registry
25
23
  end
24
+
25
+ it 'sepcifies provider' do
26
+ class InactiveWorker
27
+ include Toiler::Worker
28
+ toiler_options queue: 'gcp_queue', provider: :gcp
29
+ def perform(sqs_message, body); end
30
+ end
31
+
32
+ Toiler.options.merge!(active_queues: ['gcp_queue'])
33
+ expect(Toiler::Actor::Fetcher).to receive(:spawn!).with(name: :fetcher_gcp_queue, supervise: true, args: ['gcp_queue', 1, :gcp])
34
+ expect(Concurrent::Actor::Utils::Pool).to receive(:spawn!).with(:processor_pool_gcp_queue, 1)
35
+ supervisor = described_class.new
36
+ end
26
37
  end
27
38
  end