proletariat 0.0.2 → 0.0.3
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.
- checksums.yaml +7 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +12 -0
- data/README.md +1 -2
- data/lib/proletariat/concurrency/actor.rb +71 -0
- data/lib/proletariat/concurrency/supervisor.rb +31 -0
- data/lib/proletariat/configuration.rb +131 -0
- data/lib/proletariat/cucumber.rb +6 -2
- data/lib/proletariat/manager.rb +20 -66
- data/lib/proletariat/publisher.rb +27 -51
- data/lib/proletariat/queue_config.rb +1 -5
- data/lib/proletariat/runner.rb +10 -106
- data/lib/proletariat/subscriber.rb +6 -8
- data/lib/proletariat/testing/expectation_guarantor.rb +5 -9
- data/lib/proletariat/testing.rb +1 -1
- data/lib/proletariat/util/worker_description_parser.rb +37 -0
- data/lib/proletariat/version.rb +1 -1
- data/lib/proletariat/worker.rb +17 -41
- data/lib/proletariat.rb +24 -51
- data/spec/lib/configuration_spec.rb +85 -0
- data/spec/lib/proletariat_spec.rb +5 -4
- data/spec/lib/publisher_spec.rb +36 -0
- data/spec/lib/queue_config_spec.rb +12 -0
- data/spec/lib/testing/expectation_guarantor_spec.rb +55 -0
- data/spec/lib/testing/expectation_spec.rb +15 -0
- data/spec/lib/util/worker_description_parser_spec.rb +42 -0
- data/spec/lib/worker_spec.rb +83 -0
- metadata +34 -25
@@ -8,19 +8,17 @@ module Proletariat
|
|
8
8
|
|
9
9
|
# Public: Creates a new Subscriber instance.
|
10
10
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
def initialize(connection, listener, queue_config)
|
15
|
-
@connection = connection
|
11
|
+
# listener - Object to delegate new messages to.
|
12
|
+
# queue_config - A QueueConfig value object.
|
13
|
+
def initialize(listener, queue_config)
|
16
14
|
@listener = listener
|
17
15
|
@queue_config = queue_config
|
18
16
|
|
19
|
-
@channel =
|
17
|
+
@channel = Proletariat.connection.create_channel
|
20
18
|
|
21
|
-
@channel.prefetch
|
19
|
+
@channel.prefetch Proletariat.worker_threads
|
22
20
|
|
23
|
-
@exchange = @channel.topic
|
21
|
+
@exchange = @channel.topic Proletariat.exchange_name, durable: true
|
24
22
|
@bunny_queue = @channel.queue queue_config.queue_name,
|
25
23
|
durable: true,
|
26
24
|
auto_delete: queue_config.auto_delete
|
@@ -19,7 +19,6 @@ module Proletariat
|
|
19
19
|
# block - The block of code within which the expectations should
|
20
20
|
# be satisfied.
|
21
21
|
def initialize(expectations, &block)
|
22
|
-
@connection = Proletariat.runner.connection
|
23
22
|
@counters = []
|
24
23
|
@subscribers = []
|
25
24
|
|
@@ -27,7 +26,7 @@ module Proletariat
|
|
27
26
|
queue_config = generate_queue_config_for_topic(expectation.topics)
|
28
27
|
counter = MessageCounter.new(expectation.quantity)
|
29
28
|
counters << counter
|
30
|
-
subscribers << Subscriber.new(
|
29
|
+
subscribers << Subscriber.new(counter, queue_config)
|
31
30
|
end
|
32
31
|
|
33
32
|
@block = block
|
@@ -40,7 +39,7 @@ module Proletariat
|
|
40
39
|
def guarantee
|
41
40
|
run_subscribers
|
42
41
|
|
43
|
-
block.call
|
42
|
+
block.call if block
|
44
43
|
|
45
44
|
timer = 0.0
|
46
45
|
|
@@ -61,9 +60,6 @@ module Proletariat
|
|
61
60
|
# satisfied.
|
62
61
|
attr_reader :block
|
63
62
|
|
64
|
-
# Internal: Returns an open Bunny::Session object.
|
65
|
-
attr_reader :connection
|
66
|
-
|
67
63
|
# Internal: Returns an array of MessageCounter instances.
|
68
64
|
attr_reader :counters
|
69
65
|
|
@@ -71,7 +67,7 @@ module Proletariat
|
|
71
67
|
attr_reader :subscribers
|
72
68
|
|
73
69
|
def generate_queue_config_for_topic(topics)
|
74
|
-
QueueConfig.new('',
|
70
|
+
QueueConfig.new('', topics, true)
|
75
71
|
end
|
76
72
|
|
77
73
|
# Internal: Checks each counter to ensure expected messages have arrived.
|
@@ -107,8 +103,8 @@ module Proletariat
|
|
107
103
|
# Public: Creates a new MessageCounter instance.
|
108
104
|
#
|
109
105
|
# expected - The number of messages expected.
|
110
|
-
def initialize(expected)
|
111
|
-
@count =
|
106
|
+
def initialize(expected, count = 0)
|
107
|
+
@count = count
|
112
108
|
@expected = expected
|
113
109
|
end
|
114
110
|
|
data/lib/proletariat/testing.rb
CHANGED
@@ -4,7 +4,7 @@ require 'proletariat/testing/fixnum_extension'
|
|
4
4
|
|
5
5
|
module Proletariat
|
6
6
|
# Public: Mixin to aid solve test synchronization issues while still running
|
7
|
-
# Proletariat the same way you would in production
|
7
|
+
# Proletariat the same way you would in production.
|
8
8
|
module Testing
|
9
9
|
# Public: Builds an Expectation instance which listens for a single message
|
10
10
|
# on any topic.
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Proletariat
|
2
|
+
# Internal: Helper utility to parse and constantize strings into arrays of
|
3
|
+
# Worker classes.
|
4
|
+
module WorkerDescriptionParser
|
5
|
+
# Public: Parse given string into array of Worker classes.
|
6
|
+
#
|
7
|
+
# description - String to be parsed. Should contain comma-separated class
|
8
|
+
# names.
|
9
|
+
#
|
10
|
+
# Examples
|
11
|
+
#
|
12
|
+
# WorkerDescriptionParser.parse('FirstWorker,SecondWorker')
|
13
|
+
# # => [FirstWorker, SecondWorker]
|
14
|
+
#
|
15
|
+
# Returns an Array of Worker classes.
|
16
|
+
def self.parse(description)
|
17
|
+
description.split(',').map(&:strip).map do |string|
|
18
|
+
constantize string
|
19
|
+
end.compact
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# Intenal: Performs constantizing of worker names into Classes.
|
25
|
+
#
|
26
|
+
# name - The name to be constantized.
|
27
|
+
#
|
28
|
+
# Returns the Worker class if valid.
|
29
|
+
# Returns the nil if Worker class cannot be found.
|
30
|
+
def self.constantize(name)
|
31
|
+
name.split('::').reduce(Object) { |a, e| a.const_get(e) }
|
32
|
+
rescue NameError => e
|
33
|
+
Proletariat.logger.warn "Missing worker class: #{e.name}"
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/proletariat/version.rb
CHANGED
data/lib/proletariat/worker.rb
CHANGED
@@ -1,48 +1,39 @@
|
|
1
|
+
require 'proletariat/concerns/logging'
|
2
|
+
|
1
3
|
module Proletariat
|
2
|
-
# Public: Handles messages
|
4
|
+
# Public: Handles messages for Background processing. Subclasses should
|
3
5
|
# overwrite the #work method.
|
4
|
-
class Worker
|
6
|
+
class Worker
|
5
7
|
include Concerns::Logging
|
6
8
|
|
7
|
-
#
|
8
|
-
# messages. Overridden in this subclass to call the #work method
|
9
|
-
# with the given message.
|
10
|
-
#
|
11
|
-
# message - The incoming message.
|
9
|
+
# Public: Logs the 'online' status of the worker.
|
12
10
|
#
|
13
11
|
# Returns nil.
|
14
|
-
def
|
15
|
-
|
12
|
+
def started
|
13
|
+
log_info 'Now online'
|
14
|
+
|
15
|
+
nil
|
16
16
|
end
|
17
17
|
|
18
|
-
#
|
19
|
-
# in this subclass to log the status of the worker.
|
18
|
+
# Public: Logs the 'offline' status of the worker.
|
20
19
|
#
|
21
20
|
# Returns nil.
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
log_info 'Now online'
|
21
|
+
def stopped
|
22
|
+
log_info 'Now offline'
|
26
23
|
|
27
24
|
nil
|
28
25
|
end
|
29
26
|
|
30
|
-
#
|
31
|
-
# in this subclass to log the status of the worker.
|
27
|
+
# Public: Logs the 'shutting down' status of the worker.
|
32
28
|
#
|
33
29
|
# Returns nil.
|
34
|
-
def
|
30
|
+
def stopping
|
35
31
|
log_info 'Attempting graceful shutdown.'
|
36
|
-
wait_for_work_queue unless queue.empty?
|
37
|
-
|
38
|
-
super
|
39
|
-
|
40
|
-
log_info 'Now offline'
|
41
32
|
|
42
33
|
nil
|
43
34
|
end
|
44
35
|
|
45
|
-
# Public: Handles
|
36
|
+
# Public: Handles an incoming message to perform background work.
|
46
37
|
#
|
47
38
|
# message - The incoming message.
|
48
39
|
#
|
@@ -51,8 +42,6 @@ module Proletariat
|
|
51
42
|
fail NotImplementedError
|
52
43
|
end
|
53
44
|
|
54
|
-
protected
|
55
|
-
|
56
45
|
# Public: Helper method to ease accessing the logger from within #work.
|
57
46
|
# Sends #info to logger if message provided.
|
58
47
|
#
|
@@ -90,19 +79,6 @@ module Proletariat
|
|
90
79
|
nil
|
91
80
|
end
|
92
81
|
|
93
|
-
private
|
94
|
-
|
95
|
-
# Internal: Blocks until each message has been handled by #work.
|
96
|
-
#
|
97
|
-
# Returns nil.
|
98
|
-
def wait_for_work_queue
|
99
|
-
log_info 'Waiting for work queue to drain.'
|
100
|
-
|
101
|
-
work(*queue.pop.message) until queue.empty?
|
102
|
-
|
103
|
-
nil
|
104
|
-
end
|
105
|
-
|
106
82
|
# Internal: Class methods on Worker to provide configuration DSL.
|
107
83
|
module ConfigurationMethods
|
108
84
|
# Public: A configuration method for adding a routing key to be used when
|
@@ -111,8 +87,8 @@ module Proletariat
|
|
111
87
|
# routing_key - A routing key for queue-binding as a String.
|
112
88
|
#
|
113
89
|
# Returns nil.
|
114
|
-
def listen_on(
|
115
|
-
routing_keys
|
90
|
+
def listen_on(*new_routing_keys)
|
91
|
+
routing_keys.concat new_routing_keys
|
116
92
|
|
117
93
|
nil
|
118
94
|
end
|
data/lib/proletariat.rb
CHANGED
@@ -5,8 +5,12 @@ require 'bunny'
|
|
5
5
|
require 'logger'
|
6
6
|
require 'forwardable'
|
7
7
|
|
8
|
-
require 'proletariat/
|
8
|
+
require 'proletariat/concurrency/actor'
|
9
|
+
require 'proletariat/concurrency/supervisor'
|
9
10
|
|
11
|
+
require 'proletariat/util/worker_description_parser'
|
12
|
+
|
13
|
+
require 'proletariat/configuration'
|
10
14
|
require 'proletariat/manager'
|
11
15
|
require 'proletariat/publisher'
|
12
16
|
require 'proletariat/queue_config'
|
@@ -15,73 +19,42 @@ require 'proletariat/subscriber'
|
|
15
19
|
require 'proletariat/worker'
|
16
20
|
|
17
21
|
# Public: Creates the Proletariat namespace and holds a process-wide Runner
|
18
|
-
# instance as well as
|
22
|
+
# instance as well as access to the configuration attributes.
|
19
23
|
module Proletariat
|
20
|
-
# Public: The default name used for the RabbitMQ topic exchange.
|
21
|
-
DEFAULT_EXCHANGE_NAME = 'proletariat'
|
22
|
-
|
23
24
|
class << self
|
24
25
|
extend Forwardable
|
25
26
|
|
26
27
|
# Public: Delegate lifecycle calls to the process-wide Runner.
|
27
28
|
def_delegators :runner, :run, :run!, :stop, :running?, :publish, :purge
|
28
29
|
|
29
|
-
# Public: Allows
|
30
|
+
# Public: Allows configuration of Proletariat via given block.
|
30
31
|
#
|
31
|
-
#
|
32
|
-
attr_writer :logger
|
33
|
-
|
34
|
-
# Public: Sets the process-wide Runner to an instance initialized with a
|
35
|
-
# given hash of options.
|
32
|
+
# block - Block containing configuration calls.
|
36
33
|
#
|
37
|
-
#
|
38
|
-
|
39
|
-
|
40
|
-
# String.
|
41
|
-
# :logger - An object which fulfills the role of a
|
42
|
-
# Logger.
|
43
|
-
# :publisher_threads - The size of the publisher thread pool.
|
44
|
-
# :supervisor - A Supervisor instance.
|
45
|
-
# :worker_classes - An Array of Worker subclasses.
|
46
|
-
# :worker_threads - The size of the worker thread pool.
|
47
|
-
def configure(options = {})
|
48
|
-
self.logger = options.fetch(:logger, default_logger)
|
34
|
+
# Returns nil.
|
35
|
+
def configure(&block)
|
36
|
+
config.configure_with_block(&block)
|
49
37
|
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
# Internal: The logger used if no other is specified via .configure.
|
54
|
-
#
|
55
|
-
# Returns a Logger which logs to STDOUT.
|
56
|
-
def default_logger
|
57
|
-
Logger.new(STDOUT)
|
38
|
+
nil
|
58
39
|
end
|
59
40
|
|
60
|
-
|
61
|
-
|
62
|
-
# Returns a Hash of options.
|
63
|
-
def defaults
|
64
|
-
{
|
65
|
-
worker_classes: workers_from_env || []
|
66
|
-
}
|
41
|
+
def runner
|
42
|
+
@runner ||= Runner.new
|
67
43
|
end
|
68
44
|
|
69
|
-
def
|
70
|
-
|
45
|
+
def method_missing(method_sym, *arguments, &block)
|
46
|
+
if config.respond_to? method_sym
|
47
|
+
config.send method_sym
|
48
|
+
else
|
49
|
+
super
|
50
|
+
end
|
71
51
|
end
|
72
52
|
|
73
|
-
|
74
|
-
@runner ||= Runner.new(defaults)
|
75
|
-
end
|
53
|
+
private
|
76
54
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
string
|
81
|
-
.split('::')
|
82
|
-
.reduce(Object) { |a, e| a.const_get(e) }
|
83
|
-
end
|
84
|
-
end
|
55
|
+
# Internal: Global configuration object.
|
56
|
+
def config
|
57
|
+
@config ||= Configuration.new
|
85
58
|
end
|
86
59
|
end
|
87
60
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'proletariat'
|
2
|
+
|
3
|
+
FirstWorker = Class.new
|
4
|
+
SecondWorker = Class.new
|
5
|
+
|
6
|
+
module Proletariat
|
7
|
+
describe Configuration do
|
8
|
+
describe '#configure_with_block' do
|
9
|
+
it 'should allow configuration via `config.[attribute]=`' do
|
10
|
+
configuration = Configuration.new
|
11
|
+
expect(configuration).to receive(:connection=).with('new connection')
|
12
|
+
configuration.configure_with_block do
|
13
|
+
config.connection = 'new connection'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#connection' do
|
19
|
+
let(:new_session) { double.as_null_object }
|
20
|
+
|
21
|
+
before do
|
22
|
+
stub_const 'Bunny', double(new: new_session)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should default to a creating a new bunny session' do
|
26
|
+
expect(Bunny).to receive(:new)
|
27
|
+
Configuration.new.connection
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should open any new bunny sessions' do
|
31
|
+
expect(new_session).to receive(:start)
|
32
|
+
Configuration.new.connection
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#exchange_name' do
|
37
|
+
it 'should default to proletariat' do
|
38
|
+
expect(Configuration.new.exchange_name).to eq 'proletariat'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#logger' do
|
43
|
+
it 'should default to STDOUT' do
|
44
|
+
expect(Logger).to receive(:new).with(STDOUT)
|
45
|
+
Configuration.new.logger
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#publisher_threads' do
|
50
|
+
it 'should default to 2' do
|
51
|
+
expect(Configuration.new.publisher_threads).to eq 2
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#worker_classes' do
|
56
|
+
context 'WORKERS env variable is set' do
|
57
|
+
before do
|
58
|
+
ENV['WORKERS'] = 'FirstWorker,SecondWorker'
|
59
|
+
end
|
60
|
+
|
61
|
+
after do
|
62
|
+
ENV['WORKERS'] = nil
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should default to workers in env variable' do
|
66
|
+
expect(Configuration.new.worker_classes).to \
|
67
|
+
eq [FirstWorker, SecondWorker]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'WORKERS env variable is not set' do
|
72
|
+
it 'should default to an empty array' do
|
73
|
+
expect(Configuration.new.worker_classes).to \
|
74
|
+
eq []
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe '#worker_threads' do
|
80
|
+
it 'should default to 3' do
|
81
|
+
expect(Configuration.new.worker_threads).to eq 3
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -40,10 +40,11 @@ end
|
|
40
40
|
|
41
41
|
describe Proletariat do
|
42
42
|
it 'should roughly work' do
|
43
|
-
Proletariat.configure
|
44
|
-
logger
|
45
|
-
worker_classes
|
46
|
-
|
43
|
+
Proletariat.configure do
|
44
|
+
config.logger = Logger.new('/dev/null')
|
45
|
+
config.worker_classes = [PingWorker, PongWorker]
|
46
|
+
end
|
47
|
+
|
47
48
|
Proletariat.run!
|
48
49
|
sleep 2
|
49
50
|
Proletariat.publish 'ping', ''
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'proletariat/publisher'
|
2
|
+
|
3
|
+
module Proletariat
|
4
|
+
describe Publisher do
|
5
|
+
let(:connection) { double.as_null_object }
|
6
|
+
let(:exchange_name) { 'great-exchange' }
|
7
|
+
let(:logger) { double }
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow(Proletariat).to receive(:connection).and_return(connection)
|
11
|
+
allow(Proletariat).to receive(:exchange_name).and_return(exchange_name)
|
12
|
+
allow(Proletariat).to receive(:logger).and_return(logger)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#started' do
|
16
|
+
it 'should log status' do
|
17
|
+
expect(logger).to receive(:info).with /online/
|
18
|
+
Publisher.new.started
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#stopped' do
|
23
|
+
it 'should log status' do
|
24
|
+
expect(logger).to receive(:info).with /offline/
|
25
|
+
Publisher.new.stopped
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#stopping' do
|
30
|
+
it 'should log status' do
|
31
|
+
expect(logger).to receive(:info).with /graceful shutdown/
|
32
|
+
Publisher.new.stopping
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'proletariat/queue_config'
|
2
|
+
|
3
|
+
module Proletariat
|
4
|
+
describe QueueConfig do
|
5
|
+
describe '#queue_name' do
|
6
|
+
it 'should return an underscored version of the worker name' do
|
7
|
+
queue_config = QueueConfig.new('ExampleWorker', ['lolcats'], false)
|
8
|
+
expect(queue_config.queue_name).to eq 'example_worker'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'proletariat/testing/expectation_guarantor'
|
2
|
+
|
3
|
+
module Proletariat
|
4
|
+
module Testing
|
5
|
+
describe ExpectationGuarantor::MessageCounter do
|
6
|
+
describe '#expected_messages_received?' do
|
7
|
+
context 'count is equal or greater than expected' do
|
8
|
+
it 'should return true' do
|
9
|
+
counter = ExpectationGuarantor::MessageCounter.new(1, 3)
|
10
|
+
expect(counter.expected_messages_received?).to be_truthy
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'count is less than expected' do
|
15
|
+
it 'should return false' do
|
16
|
+
counter = ExpectationGuarantor::MessageCounter.new(5, 3)
|
17
|
+
expect(counter.expected_messages_received?).to be_falsey
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#post?' do
|
23
|
+
class FakeBlockTaker
|
24
|
+
attr_reader :block
|
25
|
+
|
26
|
+
def initialize(&block)
|
27
|
+
@block = block
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
before do
|
32
|
+
stub_const 'Concurrent::Future', FakeBlockTaker
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should increment the count' do
|
36
|
+
counter = ExpectationGuarantor::MessageCounter.new(1)
|
37
|
+
counter.post?('message')
|
38
|
+
expect(counter.expected_messages_received?).to be_truthy
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should return a future containing :ok' do
|
42
|
+
counter = ExpectationGuarantor::MessageCounter.new(1)
|
43
|
+
expect(Concurrent::Future).to receive(:new)
|
44
|
+
counter.post?('message')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should ensure the returned future contains :ok' do
|
48
|
+
counter = ExpectationGuarantor::MessageCounter.new(1)
|
49
|
+
future = counter.post?('message')
|
50
|
+
expect(future.block.call).to eq :ok
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'proletariat/testing/expectation'
|
2
|
+
|
3
|
+
module Proletariat
|
4
|
+
module Testing
|
5
|
+
describe Expectation do
|
6
|
+
describe '#on_topic' do
|
7
|
+
it 'should return a new expectation with given topic' do
|
8
|
+
expectation = Expectation.new([], 2)
|
9
|
+
expect(expectation.on_topic('lolcats', 'dogs').topics).to \
|
10
|
+
eq %w(lolcats dogs)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'proletariat/util/worker_description_parser'
|
2
|
+
|
3
|
+
FakeWorker = Class.new
|
4
|
+
AnotherFakeWorker = Class.new
|
5
|
+
|
6
|
+
module Proletariat
|
7
|
+
describe WorkerDescriptionParser do
|
8
|
+
describe '.parse' do
|
9
|
+
let(:logger) { double.as_null_object }
|
10
|
+
|
11
|
+
before do
|
12
|
+
stub_const 'Proletariat', double(logger: logger)
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'worker classes exist' do
|
16
|
+
it 'should return the worker classes' do
|
17
|
+
parsed = WorkerDescriptionParser.parse 'FakeWorker,AnotherFakeWorker'
|
18
|
+
expect(parsed).to eq [FakeWorker, AnotherFakeWorker]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'worker classes do not exist' do
|
23
|
+
it 'should return an empty array' do
|
24
|
+
parsed = WorkerDescriptionParser.parse('NonexistantWorker')
|
25
|
+
expect(parsed).to eq []
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should log a warning for the missing class' do
|
29
|
+
expect(logger).to receive(:warn).with(/Missing worker class/)
|
30
|
+
WorkerDescriptionParser.parse('NonexistantWorker')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'some worker classes exist' do
|
35
|
+
it 'should return only the existing classes' do
|
36
|
+
parsed = WorkerDescriptionParser.parse 'FakeWorker,NonexistantWorker'
|
37
|
+
expect(parsed).to eq [FakeWorker]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|