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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 49905f9a8ecb2a3b12f565f7b6c7e07c7cac6e39
|
4
|
+
data.tar.gz: 76771f1121f542f06a8ee2d9f6f7ffcf07982404
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5a1e573f1fd1028068f5f91dcd5625d4ddf90052d9711b8c8a85d810db0ea4b0440cb51384040c865eea540cbbf48368dc7b2dacdc770e85fa0430b5f63f887d
|
7
|
+
data.tar.gz: 193ecfabdc6bb3c0d25bda8a8e57a66a77aa6ab830a552f395acc626a88803ef556019556a950201a302089a830d8328fa42690943dca4a9376a345c98200217
|
data/.rubocop.yml
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## 0.0.3
|
2
|
+
|
3
|
+
Features:
|
4
|
+
|
5
|
+
- Overhauled configuration (breaking change)
|
6
|
+
- Queues now purged before first cucumber scenario
|
7
|
+
|
8
|
+
Code gardening:
|
9
|
+
|
10
|
+
- Decoupling logic from concurrency for better testability
|
11
|
+
- Added tests
|
12
|
+
|
1
13
|
## 0.0.2
|
2
14
|
|
3
15
|
Features:
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Lightweight background processing in Ruby powered by RabbitMQ and the excellent concurrent-ruby gem.
|
4
4
|
|
5
|
-
[](https://codeclimate.com/github/SebastianEdwards/proletariat)
|
6
6
|
|
7
7
|
### Warning!
|
8
8
|
|
@@ -100,6 +100,5 @@ Use the provided helpers in your step definitions to synchronize your test suite
|
|
100
100
|
I wanted a library which shared one RabbitMQ connection across all of the workers on a given process. Many hosted RabbitMQ platforms tightly limit the max number of connections.
|
101
101
|
|
102
102
|
## TODO
|
103
|
-
- Improve test suite :(
|
104
103
|
- Add command line interface
|
105
104
|
- Abstract retry strategies
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Proletariat
|
2
|
+
# Public: Interface abstraction for Concurrent::Actor. Creates a delegate
|
3
|
+
# instance from given class and arguments and delegates events to it.
|
4
|
+
class Actor < Concurrent::Actor
|
5
|
+
# Public: Creates a new Actor instance.
|
6
|
+
#
|
7
|
+
# delegate_class - The class to instantiate as a delegate.
|
8
|
+
# *arguments - The arguments to pass to delegate_class.new
|
9
|
+
def initialize(delegate_class, *arguments)
|
10
|
+
@delegate = delegate_class.new(*arguments)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Internal: Called by the Concurrent framework to handle new mailbox
|
14
|
+
# messages. Overridden in this subclass to call the #work method
|
15
|
+
# with the given arguments on the delegate.
|
16
|
+
#
|
17
|
+
# *arguments - The arguments to pass to delegate#work
|
18
|
+
#
|
19
|
+
# Returns nil.
|
20
|
+
def act(*arguments)
|
21
|
+
delegate.work(*arguments)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Internal: Called by the Concurrent framework on actor start. Overridden
|
25
|
+
# in this subclass to call the #starting and #started methods on
|
26
|
+
# the delegate.
|
27
|
+
#
|
28
|
+
# Returns nil.
|
29
|
+
def on_run
|
30
|
+
delegate.starting if delegate.respond_to?(:starting)
|
31
|
+
|
32
|
+
super
|
33
|
+
|
34
|
+
delegate.started if delegate.respond_to?(:started)
|
35
|
+
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
# Internal: Called by the Concurrent framework on actor start. Overridden
|
40
|
+
# in this subclass to call the #stopping and #stopped methods on
|
41
|
+
# the delegate. Ensures queue is drained before calling #stopped.
|
42
|
+
#
|
43
|
+
# Returns nil.
|
44
|
+
def on_stop
|
45
|
+
delegate.stopping if delegate.respond_to?(:stopping)
|
46
|
+
|
47
|
+
wait_for_queue_to_drain unless queue.empty?
|
48
|
+
|
49
|
+
super
|
50
|
+
|
51
|
+
delegate.stopped if delegate.respond_to?(:stopped)
|
52
|
+
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Internal: Returns the delegate instance.
|
59
|
+
attr_reader :delegate
|
60
|
+
|
61
|
+
# Internal: Blocks until each queued message has been handled by the
|
62
|
+
# delegate #work method.
|
63
|
+
#
|
64
|
+
# Returns nil.
|
65
|
+
def wait_for_queue_to_drain
|
66
|
+
delegate.work(*queue.pop.message) until queue.empty?
|
67
|
+
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Proletariat
|
2
|
+
class Supervisor
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
def_delegators :true_supervisor, :run, :run!, :stop, :running?, :add_worker
|
6
|
+
|
7
|
+
def [](mailbox_name)
|
8
|
+
mailboxes[mailbox_name]
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_supervisor(supervisor, opts = {})
|
12
|
+
true_supervisor.add_worker supervisor, opts.merge(type: :supervisor)
|
13
|
+
end
|
14
|
+
|
15
|
+
def supervise_pool(mailbox_name, threads, actor_class, *arguments)
|
16
|
+
mailboxes[mailbox_name], workers = Actor.pool(threads, actor_class,
|
17
|
+
*arguments)
|
18
|
+
true_supervisor.add_workers workers
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def mailboxes
|
24
|
+
@mailboxes ||= {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def true_supervisor
|
28
|
+
@true_supervisor ||= Concurrent::Supervisor.new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Proletariat
|
2
|
+
# Public: Global configuration object. Provides sensible defaults.
|
3
|
+
class Configuration
|
4
|
+
# Public: The default name used for the RabbitMQ topic exchange.
|
5
|
+
DEFAULT_EXCHANGE_NAME = 'proletariat'
|
6
|
+
|
7
|
+
# Public: The default number of threads to use for publishers.
|
8
|
+
DEFAULT_PUBLISHER_THREADS = 2
|
9
|
+
|
10
|
+
# Public: The default number of threads to use for each worker class.
|
11
|
+
DEFAULT_WORKER_THREADS = 3
|
12
|
+
|
13
|
+
# Internal: Sets the RabbitMQ connection.
|
14
|
+
attr_writer :connection
|
15
|
+
|
16
|
+
# Internal: Sets the RabbitMQ topic exchange name.
|
17
|
+
attr_writer :exchange_name
|
18
|
+
|
19
|
+
# Internal: Sets the logger.
|
20
|
+
attr_writer :logger
|
21
|
+
|
22
|
+
# Internal: Sets the number of threads to use for publishers.
|
23
|
+
attr_writer :publisher_threads
|
24
|
+
|
25
|
+
# Internal: Sets the Array of Worker classes to use for background
|
26
|
+
# processing.
|
27
|
+
attr_writer :worker_classes
|
28
|
+
|
29
|
+
# Internal: Sets the number of threads to use for each Worker class.
|
30
|
+
attr_writer :worker_threads
|
31
|
+
|
32
|
+
# Public: Allows setting of the config attributes via a block.
|
33
|
+
#
|
34
|
+
# block - Block which modifies attributes by accessing them via #config.
|
35
|
+
#
|
36
|
+
# Returns nil.
|
37
|
+
def configure_with_block(&block)
|
38
|
+
ConfigurationDSL.new(self, &block).set_config
|
39
|
+
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
# Public: Returns the set connection or defaults to a new, open
|
44
|
+
# Bunny::Session
|
45
|
+
#
|
46
|
+
# Returns a Bunny::Session.
|
47
|
+
def connection
|
48
|
+
@connection ||= begin
|
49
|
+
new_connection = Bunny.new
|
50
|
+
new_connection.start
|
51
|
+
|
52
|
+
new_connection
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Public: Returns the set name of the exchange or a default.
|
57
|
+
#
|
58
|
+
# Returns a String.
|
59
|
+
def exchange_name
|
60
|
+
@exchange_name ||= DEFAULT_EXCHANGE_NAME
|
61
|
+
end
|
62
|
+
|
63
|
+
# Public: Returns the set logger or a default standard output logger.
|
64
|
+
#
|
65
|
+
# Returns a logger.
|
66
|
+
def logger
|
67
|
+
@logger ||= Logger.new(STDOUT)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Public: Returns the set number of publisher threads or a default.
|
71
|
+
#
|
72
|
+
# Returns a Fixnum.
|
73
|
+
def publisher_threads
|
74
|
+
@publisher_threads ||= DEFAULT_PUBLISHER_THREADS
|
75
|
+
end
|
76
|
+
|
77
|
+
# Public: Returns the set worker classes or a default pulled from the
|
78
|
+
# WORKERS env variable.
|
79
|
+
#
|
80
|
+
# Returns an array of Worker classes.
|
81
|
+
def worker_classes
|
82
|
+
@worker_classes ||= begin
|
83
|
+
if ENV['WORKERS']
|
84
|
+
WorkerDescriptionParser.parse ENV['WORKERS']
|
85
|
+
else
|
86
|
+
[]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Public: Returns the set number of worker threads or a default.
|
92
|
+
#
|
93
|
+
# Returns a Fixnum.
|
94
|
+
def worker_threads
|
95
|
+
@worker_threads ||= DEFAULT_WORKER_THREADS
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
# Internal: Handles running a configuration block in a context to allow
|
101
|
+
# access to the configuration object via a call to #config.
|
102
|
+
class ConfigurationDSL
|
103
|
+
# Public: Creates a new ConfigurationDSL instance.
|
104
|
+
#
|
105
|
+
# configuration - The Configuration instance you intend to update.
|
106
|
+
# block - The block containing the config settings.
|
107
|
+
def initialize(configuration, &block)
|
108
|
+
@config = configuration
|
109
|
+
@block = block
|
110
|
+
end
|
111
|
+
|
112
|
+
# Public: Runs the configuration block, exposing the configuration
|
113
|
+
# instance via the #config method.
|
114
|
+
#
|
115
|
+
# Returns nil.
|
116
|
+
def set_config
|
117
|
+
instance_eval(&block)
|
118
|
+
|
119
|
+
nil
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
# Internal: Returns the config block.
|
125
|
+
attr_reader :block
|
126
|
+
|
127
|
+
# Internal: Returns the Configuration instance.
|
128
|
+
attr_reader :config
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/lib/proletariat/cucumber.rb
CHANGED
@@ -4,8 +4,12 @@ require 'proletariat/testing'
|
|
4
4
|
World(Proletariat::Testing)
|
5
5
|
|
6
6
|
# Hide logs by default.
|
7
|
-
AfterConfiguration do |
|
8
|
-
Proletariat.
|
7
|
+
AfterConfiguration do |_|
|
8
|
+
Proletariat.configure do
|
9
|
+
config.logger = Logger.new('/dev/null')
|
10
|
+
end
|
11
|
+
|
12
|
+
Proletariat.purge
|
9
13
|
end
|
10
14
|
|
11
15
|
# Ensure Proletariat running before each test.
|
data/lib/proletariat/manager.rb
CHANGED
@@ -2,27 +2,26 @@ module Proletariat
|
|
2
2
|
# Public: Maintains a pool of worker threads and a RabbitMQ subscriber
|
3
3
|
# thread. Uses information from the worker class to generate queue
|
4
4
|
# config.
|
5
|
-
class Manager
|
5
|
+
class Manager
|
6
6
|
# Public: Creates a new Manager instance.
|
7
7
|
#
|
8
|
-
# connection - An open Bunny::Session object.
|
9
|
-
# exchange_name - A String of the RabbitMQ topic exchange.
|
10
8
|
# worker_class - A subclass of Proletariat::Worker to handle messages.
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(connection, exchange_name, worker_class, options = {})
|
14
|
-
super()
|
9
|
+
def initialize(worker_class)
|
10
|
+
@supervisor = Supervisor.new
|
15
11
|
|
16
|
-
|
17
|
-
|
18
|
-
@worker_class = worker_class
|
19
|
-
@worker_threads = options.fetch :worker_threads, 3
|
12
|
+
supervisor.supervise_pool('workers', Proletariat.worker_threads,
|
13
|
+
worker_class)
|
20
14
|
|
21
|
-
|
22
|
-
|
15
|
+
@subscriber = Subscriber.new(supervisor['workers'],
|
16
|
+
generate_queue_config(worker_class))
|
23
17
|
|
24
|
-
|
25
|
-
|
18
|
+
supervisor.add_worker subscriber
|
19
|
+
end
|
20
|
+
|
21
|
+
# Delegate lifecycle calls to supervisor. Cannot use Forwardable due to
|
22
|
+
# concurrent-ruby API checking implementation.
|
23
|
+
%w(run stop running?).each do |method|
|
24
|
+
define_method(method) { supervisor.send method }
|
26
25
|
end
|
27
26
|
|
28
27
|
# Public: Purge the RabbitMQ queue.
|
@@ -36,64 +35,19 @@ module Proletariat
|
|
36
35
|
|
37
36
|
private
|
38
37
|
|
39
|
-
# Internal: Returns an open Bunny::Session object.
|
40
|
-
attr_reader :connection
|
41
|
-
|
42
|
-
# Internal: Returns the name of the RabbitMQ topic exchange.
|
43
|
-
attr_reader :exchange_name
|
44
|
-
|
45
38
|
# Internal: Returns the Subscriber actor for this Manager.
|
46
39
|
attr_reader :subscriber
|
47
40
|
|
48
|
-
# Internal:
|
49
|
-
attr_reader :
|
50
|
-
|
51
|
-
# Internal: Returns the pool of initialized workers.
|
52
|
-
attr_reader :worker_pool
|
53
|
-
|
54
|
-
# Internal: Returns a shared mailbox for the pool of workers.
|
55
|
-
attr_reader :workers_mailbox
|
56
|
-
|
57
|
-
# Internal: Returns the number of worker threads in the worker pool.
|
58
|
-
attr_reader :worker_threads
|
59
|
-
|
60
|
-
# Internal: Assign a new Subscriber instance (configured for the current
|
61
|
-
# worker type) to the manager's subscriber property.
|
62
|
-
#
|
63
|
-
# Returns nil.
|
64
|
-
def create_subscriber
|
65
|
-
@subscriber = Subscriber.new(
|
66
|
-
connection,
|
67
|
-
workers_mailbox,
|
68
|
-
generate_queue_config
|
69
|
-
)
|
70
|
-
|
71
|
-
nil
|
72
|
-
end
|
41
|
+
# Internal: The supervisor used to manage the Workers and Subscriber
|
42
|
+
attr_reader :supervisor
|
73
43
|
|
74
|
-
# Internal:
|
75
|
-
# manager's workers_mailbox and worker_pool properties
|
76
|
-
# respectively.
|
44
|
+
# Internal: Builds a new QueueConfig from a given Worker subclass.
|
77
45
|
#
|
78
|
-
#
|
79
|
-
def create_worker_pool
|
80
|
-
@workers_mailbox, @worker_pool = worker_class.pool(worker_threads)
|
81
|
-
|
82
|
-
nil
|
83
|
-
end
|
84
|
-
|
85
|
-
# Internal: Builds a new QueueConfig object passing in some settings from
|
86
|
-
# worker_class.
|
46
|
+
# worker_class - The Worker subclass to base settings on.
|
87
47
|
#
|
88
48
|
# Returns a new QueueConfig instance.
|
89
|
-
def generate_queue_config
|
90
|
-
QueueConfig.new(
|
91
|
-
worker_class.name,
|
92
|
-
exchange_name,
|
93
|
-
worker_class.routing_keys,
|
94
|
-
worker_threads,
|
95
|
-
false
|
96
|
-
)
|
49
|
+
def generate_queue_config(worker_class)
|
50
|
+
QueueConfig.new(worker_class.name, worker_class.routing_keys, false)
|
97
51
|
end
|
98
52
|
end
|
99
53
|
end
|
@@ -1,87 +1,63 @@
|
|
1
|
+
require 'proletariat/concerns/logging'
|
2
|
+
|
1
3
|
module Proletariat
|
2
|
-
# Public:
|
3
|
-
|
4
|
-
class Publisher < Concurrent::Actor
|
4
|
+
# Public: Receives messages and publishes them to a RabbitMQ topic exchange.
|
5
|
+
class Publisher
|
5
6
|
include Concerns::Logging
|
6
7
|
|
7
8
|
# Public: Creates a new Publisher instance.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def initialize(connection, exchange_name)
|
12
|
-
@channel = connection.create_channel
|
13
|
-
@exchange = channel.topic(exchange_name, durable: true)
|
9
|
+
def initialize
|
10
|
+
@channel = Proletariat.connection.create_channel
|
11
|
+
@exchange = channel.topic(Proletariat.exchange_name, durable: true)
|
14
12
|
end
|
15
13
|
|
16
|
-
# Public:
|
17
|
-
# messages. Overridden in this subclass to push messages to a
|
18
|
-
# RabbitMQ topic exchange.
|
19
|
-
#
|
20
|
-
# to - The routing key for the message to as a String. In accordance
|
21
|
-
# with the RabbitMQ convention you can use the '*' character to
|
22
|
-
# replace one word and the '#' to replace many words.
|
23
|
-
# message - The message as a String.
|
14
|
+
# Public: Logs the 'online' status of the publisher.
|
24
15
|
#
|
25
16
|
# Returns nil.
|
26
|
-
def
|
27
|
-
|
17
|
+
def started
|
18
|
+
log_info 'Now online'
|
28
19
|
|
29
20
|
nil
|
30
21
|
end
|
31
22
|
|
32
|
-
# Public:
|
33
|
-
# this subclass to log the status of the publisher.
|
23
|
+
# Public: Logs the 'offline' status of the publisher.
|
34
24
|
#
|
35
25
|
# Returns nil.
|
36
|
-
def
|
37
|
-
|
38
|
-
log_info 'Now online'
|
26
|
+
def stopped
|
27
|
+
log_info 'Now offline'
|
39
28
|
|
40
29
|
nil
|
41
30
|
end
|
42
31
|
|
43
|
-
# Public:
|
44
|
-
#
|
45
|
-
|
32
|
+
# Public: Logs the 'shutting down' status of the publisher.
|
33
|
+
#
|
34
|
+
# Returns nil.
|
35
|
+
def stopping
|
46
36
|
log_info 'Attempting graceful shutdown.'
|
47
|
-
wait_for_publish_queue unless queue.empty?
|
48
|
-
|
49
|
-
super
|
50
|
-
|
51
|
-
log_info 'Now offline'
|
52
37
|
|
53
38
|
nil
|
54
39
|
end
|
55
40
|
|
56
|
-
|
57
|
-
|
58
|
-
# Internal: Returns the Bunny::Channel in use.
|
59
|
-
attr_reader :channel
|
60
|
-
|
61
|
-
# Internal: Returns the Bunny::Exchange in use.
|
62
|
-
attr_reader :exchange
|
63
|
-
|
64
|
-
# Internal: Handles the actual message send to the exchange.
|
41
|
+
# Public: Push a message to a RabbitMQ topic exchange.
|
65
42
|
#
|
66
|
-
# to - The routing key.
|
43
|
+
# to - The routing key for the message to as a String. In accordance
|
44
|
+
# with the RabbitMQ convention you can use the '*' character to
|
45
|
+
# replace one word and the '#' to replace many words.
|
67
46
|
# message - The message as a String.
|
68
47
|
#
|
69
48
|
# Returns nil.
|
70
|
-
def
|
49
|
+
def work(to, message)
|
71
50
|
exchange.publish message, routing_key: to, persistent: true
|
72
51
|
|
73
52
|
nil
|
74
53
|
end
|
75
54
|
|
76
|
-
|
77
|
-
#
|
78
|
-
# Returns nil.
|
79
|
-
def wait_for_publish_queue
|
80
|
-
log_info 'Waiting for work queue to drain.'
|
55
|
+
private
|
81
56
|
|
82
|
-
|
57
|
+
# Internal: Returns the Bunny::Channel in use.
|
58
|
+
attr_reader :channel
|
83
59
|
|
84
|
-
|
85
|
-
|
60
|
+
# Internal: Returns the Bunny::Exchange in use.
|
61
|
+
attr_reader :exchange
|
86
62
|
end
|
87
63
|
end
|
@@ -1,9 +1,5 @@
|
|
1
1
|
# Internal: Value object to hold RabbitMQ settings.
|
2
|
-
class QueueConfig < Struct.new(:worker_name,
|
3
|
-
:exchange_name,
|
4
|
-
:routing_keys,
|
5
|
-
:prefetch,
|
6
|
-
:auto_delete)
|
2
|
+
class QueueConfig < Struct.new(:worker_name, :routing_keys, :auto_delete)
|
7
3
|
# Public: Create an underscored RabbitMQ queue name from the worker_name.
|
8
4
|
#
|
9
5
|
# Examples
|
data/lib/proletariat/runner.rb
CHANGED
@@ -7,37 +7,16 @@ module Proletariat
|
|
7
7
|
# Public: Delegate lifecycle calls to the supervisor.
|
8
8
|
def_delegators :supervisor, :run, :run!, :stop, :running?
|
9
9
|
|
10
|
-
# Public:
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
# Public: Creates a new Runner instance. Default options should be fine for
|
17
|
-
# most scenarios.
|
18
|
-
#
|
19
|
-
# options - A Hash of options (default: {}):
|
20
|
-
# :connection - An open RabbitMQ::Session object.
|
21
|
-
# :exchange_name - The RabbitMQ topic exchange name as a
|
22
|
-
# String.
|
23
|
-
# :publisher_threads - The size of the publisher thread pool.
|
24
|
-
# :supervisor - A Supervisor instance.
|
25
|
-
# :worker_classes - An Array of Worker subclasses.
|
26
|
-
# :worker_threads - The size of the worker thread pool.
|
27
|
-
def initialize(options = {})
|
28
|
-
@connection = options.fetch :connection, create_connection
|
29
|
-
@exchange_name = options.fetch :exchange_name, DEFAULT_EXCHANGE_NAME
|
30
|
-
@publisher_threads = options.fetch :publisher_threads, 2
|
31
|
-
@supervisor = options.fetch :supervisor, create_supervisor
|
32
|
-
@worker_classes = options.fetch :worker_classes, []
|
33
|
-
@worker_threads = options.fetch :worker_threads, 3
|
34
|
-
|
35
|
-
@managers = []
|
36
|
-
|
37
|
-
create_publisher_pool
|
10
|
+
# Public: Creates a new Runner instance.
|
11
|
+
def initialize
|
12
|
+
@supervisor = Supervisor.new
|
13
|
+
@managers = Proletariat.worker_classes.map do |worker_class|
|
14
|
+
Manager.new(worker_class)
|
15
|
+
end
|
38
16
|
|
39
|
-
|
40
|
-
|
17
|
+
supervisor.supervise_pool('publishers', Proletariat.publisher_threads,
|
18
|
+
Publisher)
|
19
|
+
managers.each { |manager| supervisor.add_supervisor manager }
|
41
20
|
end
|
42
21
|
|
43
22
|
# Public: Publishes a message to RabbitMQ via the publisher pool.
|
@@ -49,7 +28,7 @@ module Proletariat
|
|
49
28
|
#
|
50
29
|
# Returns nil.
|
51
30
|
def publish(to, message)
|
52
|
-
|
31
|
+
supervisor['publishers'].post to, message
|
53
32
|
|
54
33
|
nil
|
55
34
|
end
|
@@ -68,82 +47,7 @@ module Proletariat
|
|
68
47
|
# Internal: Returns an Array of the currently supervised Managers.
|
69
48
|
attr_reader :managers
|
70
49
|
|
71
|
-
# Internal: Returns the pool of initialized publishers.
|
72
|
-
attr_reader :publisher_pool
|
73
|
-
|
74
|
-
# Internal: Returns a shared mailbox for the pool of publishers.
|
75
|
-
attr_reader :publishers_mailbox
|
76
|
-
|
77
|
-
# Internal: Returns the number of publisher threads in the publisher pool.
|
78
|
-
attr_reader :publisher_threads
|
79
|
-
|
80
50
|
# Internal: Returns the supervisor instance.
|
81
51
|
attr_reader :supervisor
|
82
|
-
|
83
|
-
# Internal: Returns an Array of Worker subclasses.
|
84
|
-
attr_reader :worker_classes
|
85
|
-
|
86
|
-
# Internal: Returns the number of worker threads per manager.
|
87
|
-
attr_reader :worker_threads
|
88
|
-
|
89
|
-
# Internal: Adds each publisher in the publisher_pool to the supervisor.
|
90
|
-
#
|
91
|
-
# Returns nil.
|
92
|
-
def add_publishers_to_supervisor
|
93
|
-
publisher_pool.each { |publisher| supervisor.add_worker publisher }
|
94
|
-
|
95
|
-
nil
|
96
|
-
end
|
97
|
-
|
98
|
-
# Internal: Creates a Manager per worker_class and adds these to the
|
99
|
-
# supervisor.
|
100
|
-
#
|
101
|
-
# Returns nil.
|
102
|
-
def add_workers_to_supervisor
|
103
|
-
worker_classes.each do |worker_class|
|
104
|
-
manager = create_manager(worker_class)
|
105
|
-
@managers << manager
|
106
|
-
supervisor.add_worker manager
|
107
|
-
end
|
108
|
-
|
109
|
-
nil
|
110
|
-
end
|
111
|
-
|
112
|
-
# Internal: Creates a new Bunny::Session and opens it.
|
113
|
-
#
|
114
|
-
# Returns an open Bunny::Session instance.
|
115
|
-
def create_connection
|
116
|
-
new_connection = Bunny.new
|
117
|
-
new_connection.start
|
118
|
-
|
119
|
-
new_connection
|
120
|
-
end
|
121
|
-
|
122
|
-
# Internal: Assign new Concurrent::Poolbox and Array[Publisher] to the
|
123
|
-
# manager's publishers_mailbox and publisher_pool properties
|
124
|
-
# respectively.
|
125
|
-
#
|
126
|
-
# Returns nil.
|
127
|
-
def create_publisher_pool
|
128
|
-
@publishers_mailbox, @publisher_pool = Publisher.pool(publisher_threads,
|
129
|
-
connection,
|
130
|
-
exchange_name)
|
131
|
-
end
|
132
|
-
|
133
|
-
# Internal: Creates a new Concurrent::Supervisor.
|
134
|
-
#
|
135
|
-
# Returns a Concurrent::Supervisor instance.
|
136
|
-
def create_supervisor
|
137
|
-
Concurrent::Supervisor.new
|
138
|
-
end
|
139
|
-
|
140
|
-
# Internal: Creates a Manager for a given Worker subclass adding relevant
|
141
|
-
# arguments from Runner properties.
|
142
|
-
#
|
143
|
-
# Returns a Manager instance.
|
144
|
-
def create_manager(worker_class)
|
145
|
-
Manager.new(connection, exchange_name, worker_class,
|
146
|
-
worker_threads: worker_threads)
|
147
|
-
end
|
148
52
|
end
|
149
53
|
end
|