chore-core 1.10.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/LICENSE.txt +1 -1
- data/README.md +172 -153
- data/chore-core.gemspec +3 -3
- data/lib/chore.rb +29 -5
- data/lib/chore/cli.rb +22 -4
- data/lib/chore/configuration.rb +1 -1
- data/lib/chore/consumer.rb +54 -12
- data/lib/chore/fetcher.rb +12 -7
- data/lib/chore/hooks.rb +2 -1
- data/lib/chore/job.rb +19 -0
- data/lib/chore/manager.rb +17 -2
- data/lib/chore/publisher.rb +18 -2
- data/lib/chore/queues/filesystem/consumer.rb +126 -64
- data/lib/chore/queues/filesystem/filesystem_queue.rb +19 -0
- data/lib/chore/queues/filesystem/publisher.rb +10 -16
- data/lib/chore/queues/sqs.rb +22 -13
- data/lib/chore/queues/sqs/consumer.rb +64 -51
- data/lib/chore/queues/sqs/publisher.rb +26 -17
- data/lib/chore/strategies/consumer/batcher.rb +6 -6
- data/lib/chore/strategies/consumer/single_consumer_strategy.rb +5 -5
- data/lib/chore/strategies/consumer/threaded_consumer_strategy.rb +7 -6
- data/lib/chore/strategies/consumer/throttled_consumer_strategy.rb +120 -0
- data/lib/chore/strategies/worker/forked_worker_strategy.rb +5 -6
- data/lib/chore/strategies/worker/helpers/ipc.rb +87 -0
- data/lib/chore/strategies/worker/helpers/preforked_worker.rb +163 -0
- data/lib/chore/strategies/worker/helpers/work_distributor.rb +65 -0
- data/lib/chore/strategies/worker/helpers/worker_info.rb +13 -0
- data/lib/chore/strategies/worker/helpers/worker_killer.rb +40 -0
- data/lib/chore/strategies/worker/helpers/worker_manager.rb +183 -0
- data/lib/chore/strategies/worker/preforked_worker_strategy.rb +150 -0
- data/lib/chore/unit_of_work.rb +2 -1
- data/lib/chore/util.rb +5 -1
- data/lib/chore/version.rb +2 -2
- data/lib/chore/worker.rb +30 -3
- data/spec/chore/cli_spec.rb +2 -2
- data/spec/chore/consumer_spec.rb +1 -5
- data/spec/chore/duplicate_detector_spec.rb +17 -5
- data/spec/chore/fetcher_spec.rb +0 -11
- data/spec/chore/manager_spec.rb +7 -0
- data/spec/chore/queues/filesystem/filesystem_consumer_spec.rb +74 -16
- data/spec/chore/queues/sqs/consumer_spec.rb +117 -78
- data/spec/chore/queues/sqs/publisher_spec.rb +49 -60
- data/spec/chore/queues/sqs_spec.rb +32 -41
- data/spec/chore/strategies/consumer/single_consumer_strategy_spec.rb +3 -3
- data/spec/chore/strategies/consumer/threaded_consumer_strategy_spec.rb +6 -6
- data/spec/chore/strategies/consumer/throttled_consumer_strategy_spec.rb +165 -0
- data/spec/chore/strategies/worker/forked_worker_strategy_spec.rb +6 -1
- data/spec/chore/strategies/worker/helpers/ipc_spec.rb +127 -0
- data/spec/chore/strategies/worker/helpers/preforked_worker_spec.rb +236 -0
- data/spec/chore/strategies/worker/helpers/work_distributor_spec.rb +131 -0
- data/spec/chore/strategies/worker/helpers/worker_info_spec.rb +14 -0
- data/spec/chore/strategies/worker/helpers/worker_killer_spec.rb +97 -0
- data/spec/chore/strategies/worker/helpers/worker_manager_spec.rb +304 -0
- data/spec/chore/strategies/worker/preforked_worker_strategy_spec.rb +183 -0
- data/spec/chore/strategies/worker/single_worker_strategy_spec.rb +1 -1
- data/spec/chore/worker_spec.rb +70 -15
- data/spec/spec_helper.rb +1 -1
- data/spec/support/queues/sqs/fake_objects.rb +18 -0
- metadata +53 -29
data/chore-core.gemspec
CHANGED
@@ -37,10 +37,10 @@ Gem::Specification.new do |s|
|
|
37
37
|
s.summary = "Job processing... for the future!"
|
38
38
|
|
39
39
|
s.add_runtime_dependency(%q<json>, [">= 0"])
|
40
|
-
s.add_runtime_dependency(%q<aws-sdk-
|
40
|
+
s.add_runtime_dependency(%q<aws-sdk-sqs>, ["~> 1"])
|
41
41
|
s.add_runtime_dependency(%q<thread>, ["~> 0.1.3"])
|
42
|
-
s.
|
42
|
+
s.add_runtime_dependency('get_process_mem', ["~> 0.2.0"])
|
43
|
+
s.add_development_dependency(%q<rspec>, ["~> 3.3"])
|
43
44
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
44
45
|
s.add_development_dependency(%q<bundler>, [">= 0"])
|
45
46
|
end
|
46
|
-
|
data/lib/chore.rb
CHANGED
@@ -41,7 +41,11 @@ module Chore #:nodoc:
|
|
41
41
|
:shutdown_timeout => (2 * 60),
|
42
42
|
:max_attempts => 1.0 / 0.0, # Infinity
|
43
43
|
:dupe_on_cache_failure => false,
|
44
|
-
:
|
44
|
+
:queue_polling_size => 10,
|
45
|
+
:payload_handler => Chore::Job,
|
46
|
+
:master_procline => "chore-master-#{Chore::VERSION}",
|
47
|
+
:worker_procline => "chore-worker-#{Chore::VERSION}",
|
48
|
+
:consumer_sleep_interval => 1
|
45
49
|
}
|
46
50
|
|
47
51
|
class << self
|
@@ -59,6 +63,24 @@ module Chore #:nodoc:
|
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
66
|
+
def self.log_level_to_sym
|
67
|
+
return self.config[:log_level] if self.config[:log_level].is_a?(Symbol)
|
68
|
+
case self.config[:log_level]
|
69
|
+
when 0
|
70
|
+
:debug
|
71
|
+
when 1
|
72
|
+
:info
|
73
|
+
when 2
|
74
|
+
:warn
|
75
|
+
when 3
|
76
|
+
:error
|
77
|
+
when 4
|
78
|
+
:fatal
|
79
|
+
else
|
80
|
+
:unknown
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
62
84
|
# Reopens any open files. This will match any logfile that was opened by Chore,
|
63
85
|
# Rails, or any other library.
|
64
86
|
def self.reopen_logs
|
@@ -111,9 +133,9 @@ module Chore #:nodoc:
|
|
111
133
|
# add_hook(:before_fork) {|worker| puts 1 }
|
112
134
|
# add_hook(:before_fork) {|worker| puts 2 }
|
113
135
|
# add_hook(:before_fork) {|worker| puts 3 }
|
114
|
-
#
|
136
|
+
#
|
115
137
|
# run_hooks_for(:before_fork, worker)
|
116
|
-
#
|
138
|
+
#
|
117
139
|
# # ...will produce the following output
|
118
140
|
# => 1
|
119
141
|
# => 2
|
@@ -130,9 +152,9 @@ module Chore #:nodoc:
|
|
130
152
|
# add_hook(:around_fork) {|worker, &block| puts 'before 1'; block.call; puts 'after 1'}
|
131
153
|
# add_hook(:around_fork) {|worker, &block| puts 'before 2'; block.call; puts 'after 2'}
|
132
154
|
# add_hook(:around_fork) {|worker, &block| puts 'before 3'; block.call; puts 'after 3'}
|
133
|
-
#
|
155
|
+
#
|
134
156
|
# run_hooks_for(:around_fork, worker) { puts 'block' }
|
135
|
-
#
|
157
|
+
#
|
136
158
|
# # ...will produce the following output
|
137
159
|
# => before 1
|
138
160
|
# => before 2
|
@@ -214,6 +236,8 @@ module Chore #:nodoc:
|
|
214
236
|
end
|
215
237
|
|
216
238
|
# List of queue_names as configured via Chore::Job including their prefix, if set.
|
239
|
+
#
|
240
|
+
# @return [Array<String>]
|
217
241
|
def self.prefixed_queue_names
|
218
242
|
Chore::Job.job_classes.collect {|klass| c = constantize(klass); c.prefixed_queue_name}
|
219
243
|
end
|
data/lib/chore/cli.rb
CHANGED
@@ -89,10 +89,11 @@ module Chore #:nodoc:
|
|
89
89
|
detect_queues
|
90
90
|
Chore.configure(options)
|
91
91
|
Chore.configuring = false
|
92
|
+
validate_strategy!
|
92
93
|
end
|
93
94
|
|
94
|
-
|
95
95
|
private
|
96
|
+
|
96
97
|
def setup_options #:nodoc:
|
97
98
|
register_option "queues", "-q", "--queues QUEUE1,QUEUE2", "Names of queues to process (default: all known)" do |arg|
|
98
99
|
# This will remove duplicates. We ultimately force this to be a Set further below
|
@@ -134,7 +135,7 @@ module Chore #:nodoc:
|
|
134
135
|
options[:consumer_strategy] = constantize(arg)
|
135
136
|
end
|
136
137
|
|
137
|
-
register_option 'consumer_sleep_interval', '--consumer-sleep-interval INTERVAL', Float, 'Length of time in seconds to sleep when the consumer does not find any messages
|
138
|
+
register_option 'consumer_sleep_interval', '--consumer-sleep-interval INTERVAL', Float, 'Length of time in seconds to sleep when the consumer does not find any messages (default: 1)'
|
138
139
|
|
139
140
|
register_option 'payload_handler', '--payload_handler CLASS_NAME', 'Name of a class to use as the payload handler (default: Chore::Job)' do |arg|
|
140
141
|
options[:payload_handler] = constantize(arg)
|
@@ -144,6 +145,7 @@ module Chore #:nodoc:
|
|
144
145
|
|
145
146
|
register_option 'dupe_on_cache_failure', '--dupe-on-cache-failure BOOLEAN', 'Determines the deduping behavior when a cache connection error occurs. When set to false, the message is assumed not to be a duplicate. (default: false)'
|
146
147
|
|
148
|
+
register_option 'queue_polling_size', '--queue_polling_size NUM', Integer, 'Amount of messages to grab on each request (default: 10)'
|
147
149
|
end
|
148
150
|
|
149
151
|
def parse_opts(argv, ignore_errors = false) #:nodoc:
|
@@ -254,7 +256,6 @@ module Chore #:nodoc:
|
|
254
256
|
end
|
255
257
|
|
256
258
|
def validate! #:nodoc:
|
257
|
-
|
258
259
|
missing_option!("--require [PATH|DIR]") unless options[:require]
|
259
260
|
|
260
261
|
if !File.exist?(options[:require]) ||
|
@@ -266,8 +267,25 @@ module Chore #:nodoc:
|
|
266
267
|
puts @parser
|
267
268
|
exit(1)
|
268
269
|
end
|
270
|
+
end
|
269
271
|
|
272
|
+
def validate_strategy!
|
273
|
+
consumer_strategy = Chore.config.consumer_strategy.to_s
|
274
|
+
worker_strategy = Chore.config.worker_strategy.to_s
|
275
|
+
|
276
|
+
throttled_consumer = 'Chore::Strategy::ThrottledConsumerStrategy'
|
277
|
+
preforked_worker = 'Chore::Strategy::PreForkedWorkerStrategy'
|
278
|
+
|
279
|
+
if consumer_strategy == throttled_consumer || worker_strategy == preforked_worker
|
280
|
+
unless consumer_strategy == throttled_consumer && worker_strategy == preforked_worker
|
281
|
+
puts "=================================================================="
|
282
|
+
puts " PreForkedWorkerStrategy may only be paired with "
|
283
|
+
puts " ThrottledConsumerStrategy or vice versa "
|
284
|
+
puts " Please check your configurations "
|
285
|
+
puts "=================================================================="
|
286
|
+
exit(1)
|
287
|
+
end
|
288
|
+
end
|
270
289
|
end
|
271
290
|
end
|
272
291
|
end
|
273
|
-
|
data/lib/chore/configuration.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Chore
|
2
2
|
# Wrapper around an OpenStruct to define configuration data
|
3
|
-
#
|
3
|
+
# TODO: Add required opts, and validate that they're set
|
4
4
|
class Configuration < OpenStruct
|
5
5
|
# Helper method to make merging Hashes into OpenStructs easier
|
6
6
|
def merge_hash(hsh={})
|
data/lib/chore/consumer.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
module Chore
|
2
2
|
# Raised when Chore is booting up, but encounters a set of configuration that is impossible to boot from. Typically
|
3
|
-
# you'll find additional information around the cause of the exception by examining the logfiles
|
3
|
+
# you'll find additional information around the cause of the exception by examining the logfiles.
|
4
|
+
# You can raise this exception if your queue is in a terrible state and must shut down.
|
4
5
|
class TerribleMistake < Exception
|
5
|
-
# You can raise this exception if your queue is in a terrible state and must shut down
|
6
6
|
end
|
7
7
|
|
8
|
-
# Base class for a Chore Consumer. Provides the
|
9
|
-
# Chore Consumers.
|
8
|
+
# Base class for a Chore Consumer. Provides the interface that a Chore::Consumer implementation should adhere to.
|
10
9
|
class Consumer
|
11
10
|
|
12
11
|
attr_accessor :queue_name
|
13
12
|
|
13
|
+
# @param [String] queue_name Name of queue to be consumed from
|
14
|
+
# @param [Hash] opts
|
14
15
|
def initialize(queue_name, opts={})
|
15
16
|
@queue_name = queue_name
|
16
17
|
@running = true
|
@@ -21,26 +22,28 @@ module Chore
|
|
21
22
|
def self.reset_connection!
|
22
23
|
end
|
23
24
|
|
24
|
-
# Cleans up any resources that were left behind from prior instances of the
|
25
|
-
# chore process. By default, this is a no-op.
|
26
|
-
def self.cleanup(queue)
|
27
|
-
end
|
28
|
-
|
29
25
|
# Consume takes a block with an arity of two. The two params are
|
30
26
|
# |message_id,message_body| where message_id is any object that the
|
31
27
|
# consumer will need to be able to act on a message later (reject, complete, etc)
|
32
|
-
|
28
|
+
#
|
29
|
+
# @param [Block] &handler Message handler, used by the calling context (worker) to create & assigns a UnitOfWork
|
30
|
+
def consume(&handler)
|
33
31
|
raise NotImplementedError
|
34
32
|
end
|
35
33
|
|
36
34
|
# Reject should put a message back on a queue to be processed again later. It takes
|
37
35
|
# a message_id as returned via consume.
|
36
|
+
#
|
37
|
+
# @param [String] message_id Unique ID of the message
|
38
38
|
def reject(message_id)
|
39
39
|
raise NotImplementedError
|
40
40
|
end
|
41
41
|
|
42
|
-
# Complete should mark a message as finished.
|
43
|
-
|
42
|
+
# Complete should mark a message as finished.
|
43
|
+
#
|
44
|
+
# @param [String] message_id Unique ID of the message
|
45
|
+
# @param [Hash] receipt_handle Unique ID of the consuming transaction in non-filesystem implementations
|
46
|
+
def complete(message_id, receipt_handle)
|
44
47
|
raise NotImplementedError
|
45
48
|
end
|
46
49
|
|
@@ -50,8 +53,47 @@ module Chore
|
|
50
53
|
end
|
51
54
|
|
52
55
|
# Returns true if the Consumer is currently running
|
56
|
+
#
|
57
|
+
# @return [TrueClass, FalseClass]
|
53
58
|
def running?
|
54
59
|
@running
|
55
60
|
end
|
61
|
+
|
62
|
+
# Returns up to n work
|
63
|
+
#
|
64
|
+
# @param n
|
65
|
+
def provide_work(n)
|
66
|
+
raise NotImplementedError
|
67
|
+
end
|
68
|
+
|
69
|
+
# Determine whether or not we have already seen this message
|
70
|
+
#
|
71
|
+
# @param [String] dedupe_key
|
72
|
+
# @param [Class] klass
|
73
|
+
# @param [Integer] queue_timeout
|
74
|
+
#
|
75
|
+
# @return [TrueClass, FalseClass]
|
76
|
+
def duplicate_message?(dedupe_key, klass, queue_timeout)
|
77
|
+
dupe_detector.found_duplicate?(:id=>dedupe_key, :queue=>klass.to_s, :visibility_timeout=>queue_timeout)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Instance of duplicate detection implementation class
|
81
|
+
#
|
82
|
+
# @return [DuplicateDetector]
|
83
|
+
def dupe_detector
|
84
|
+
@dupes ||= DuplicateDetector.new({:servers => Chore.config.dedupe_servers,
|
85
|
+
:dupe_on_cache_failure => false})
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# Gets messages from queue implementation and invokes the provided block over each one. Afterwards, the :on_fetch
|
91
|
+
# hook will be invoked per message. This block call provides data necessary for the worker (calling context) to
|
92
|
+
# populate a UnitOfWork struct.
|
93
|
+
#
|
94
|
+
# @param [Block] &handler Message handler, passed along by #consume
|
95
|
+
def handle_messages(&handler)
|
96
|
+
raise NotImplementedError
|
97
|
+
end
|
56
98
|
end
|
57
99
|
end
|
data/lib/chore/fetcher.rb
CHANGED
@@ -11,21 +11,16 @@ module Chore
|
|
11
11
|
# Starts the fetcher with the configured Consumer Strategy. This will begin consuming messages from your queue
|
12
12
|
def start
|
13
13
|
Chore.logger.info "Fetcher starting up"
|
14
|
-
|
15
|
-
# Clean up configured queues in case there are any resources left behind
|
16
|
-
Chore.config.queues.each do |queue|
|
17
|
-
Chore.config.consumer.cleanup(queue)
|
18
|
-
end
|
19
|
-
|
20
14
|
@strategy.fetch
|
21
15
|
end
|
22
16
|
|
23
17
|
# Stops the fetcher, preventing any further messages from being pulled from the queue
|
24
18
|
def stop!
|
25
19
|
unless @stopping
|
26
|
-
Chore.logger.info "Fetcher shutting down"
|
20
|
+
Chore.logger.info "Fetcher shutting down started"
|
27
21
|
@stopping = true
|
28
22
|
@strategy.stop!
|
23
|
+
Chore.logger.info "Fetcher shutting down completed"
|
29
24
|
end
|
30
25
|
end
|
31
26
|
|
@@ -33,5 +28,15 @@ module Chore
|
|
33
28
|
def stopping?
|
34
29
|
@stopping
|
35
30
|
end
|
31
|
+
|
32
|
+
# returns upto n work units
|
33
|
+
def provide_work(n)
|
34
|
+
@strategy.provide_work(n)
|
35
|
+
end
|
36
|
+
|
37
|
+
# gives work back to the consumer in case it couldn't be assigned
|
38
|
+
def return_work(work_units)
|
39
|
+
@strategy.return_work(work_units)
|
40
|
+
end
|
36
41
|
end
|
37
42
|
end
|
data/lib/chore/hooks.rb
CHANGED
@@ -15,7 +15,8 @@ module Chore
|
|
15
15
|
|
16
16
|
private
|
17
17
|
def hooks_for(event)
|
18
|
-
|
18
|
+
@_chore_hooks ||= {}
|
19
|
+
@_chore_hooks[event] ||= candidate_methods.grep(/^#{event}/).sort
|
19
20
|
end
|
20
21
|
|
21
22
|
# NOTE: Any hook methods defined after this is first referenced (i.e.,
|
data/lib/chore/job.rb
CHANGED
@@ -60,6 +60,12 @@ module Chore
|
|
60
60
|
raise ArgumentError, "#{self.to_s}: backoff must accept a single argument"
|
61
61
|
end
|
62
62
|
end
|
63
|
+
|
64
|
+
if @chore_options.key?(:dedupe_lambda)
|
65
|
+
if !@chore_options[:dedupe_lambda].is_a?(Proc)
|
66
|
+
raise ArgumentError, "#{self.to_s}: dedupe_lambda must be a lambda or Proc"
|
67
|
+
end
|
68
|
+
end
|
63
69
|
end
|
64
70
|
|
65
71
|
# This is a method so it can be overriden to create additional required
|
@@ -99,6 +105,8 @@ module Chore
|
|
99
105
|
end
|
100
106
|
|
101
107
|
# The name of the configured queue, combined with an optional prefix
|
108
|
+
#
|
109
|
+
# @return [String]
|
102
110
|
def prefixed_queue_name
|
103
111
|
"#{Chore.config.queue_prefix}#{self.options[:name]}"
|
104
112
|
end
|
@@ -108,6 +116,17 @@ module Chore
|
|
108
116
|
def has_backoff?
|
109
117
|
self.options.key?(:backoff)
|
110
118
|
end
|
119
|
+
|
120
|
+
def has_dedupe_lambda?
|
121
|
+
self.options.key?(:dedupe_lambda)
|
122
|
+
end
|
123
|
+
|
124
|
+
def dedupe_key(*args)
|
125
|
+
return unless has_dedupe_lambda?
|
126
|
+
|
127
|
+
# run the proc to get the key
|
128
|
+
self.options[:dedupe_lambda].call(*args).to_s
|
129
|
+
end
|
111
130
|
end #ClassMethods
|
112
131
|
|
113
132
|
# This is handy to override in an included job to be able to do job setup that requires
|
data/lib/chore/manager.rb
CHANGED
@@ -5,14 +5,15 @@ require 'chore/fetcher'
|
|
5
5
|
module Chore
|
6
6
|
# Manages the interactions between fetching messages (Consumer Strategy), and working over them (Worker Strategy)
|
7
7
|
class Manager
|
8
|
+
include Util
|
8
9
|
|
9
10
|
def initialize()
|
10
11
|
Chore.logger.info "Booting Chore #{Chore::VERSION}"
|
11
12
|
Chore.logger.debug { Chore.config.inspect }
|
13
|
+
procline("#{Chore.config.master_procline}:Started:#{Time.now}")
|
12
14
|
@started_at = nil
|
13
15
|
@worker_strategy = Chore.config.worker_strategy.new(self)
|
14
16
|
@fetcher = Chore.config.fetcher.new(self)
|
15
|
-
@processed = 0
|
16
17
|
@stopping = false
|
17
18
|
end
|
18
19
|
|
@@ -27,11 +28,12 @@ module Chore
|
|
27
28
|
# Shut down the Manager, the Worker Strategy, and the Fetcher. This calls the +:before_shutdown+ hook.
|
28
29
|
def shutdown!
|
29
30
|
unless @stopping
|
30
|
-
Chore.logger.info "Manager shutting down"
|
31
|
+
Chore.logger.info "Manager shutting down started"
|
31
32
|
@stopping = true
|
32
33
|
Chore.run_hooks_for(:before_shutdown)
|
33
34
|
@fetcher.stop!
|
34
35
|
@worker_strategy.stop!
|
36
|
+
Chore.logger.info "Manager shutting down completed"
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
@@ -42,7 +44,20 @@ module Chore
|
|
42
44
|
# than they can be consumed.
|
43
45
|
def assign(work)
|
44
46
|
Chore.logger.debug { "Manager#assign: No. of UnitsOfWork: #{work.length})" }
|
47
|
+
work.each do | item |
|
48
|
+
Chore.run_hooks_for(:before_send_to_worker, item)
|
49
|
+
end
|
45
50
|
@worker_strategy.assign(work) unless @stopping
|
46
51
|
end
|
52
|
+
|
53
|
+
# returns up to n from the throttled consumer queue
|
54
|
+
def fetch_work(n)
|
55
|
+
@fetcher.provide_work(n)
|
56
|
+
end
|
57
|
+
|
58
|
+
# gives work back to the fetcher in case it couldn't be assigned
|
59
|
+
def return_work(work_units)
|
60
|
+
@fetcher.return_work(work_units)
|
61
|
+
end
|
47
62
|
end
|
48
63
|
end
|
data/lib/chore/publisher.rb
CHANGED
@@ -1,26 +1,42 @@
|
|
1
1
|
module Chore
|
2
|
-
# Base class for Chore
|
2
|
+
# Base class for a Chore Publisher. Provides the interface that a Chore::Publisher implementation should adhere to.
|
3
3
|
class Publisher
|
4
4
|
DEFAULT_OPTIONS = { :encoder => Encoder::JsonEncoder }
|
5
5
|
|
6
6
|
attr_accessor :options
|
7
7
|
|
8
|
+
# @param [Hash] opts
|
8
9
|
def initialize(opts={})
|
9
10
|
self.options = DEFAULT_OPTIONS.merge(opts)
|
10
11
|
end
|
11
12
|
|
12
13
|
# Publishes the provided +job+ to the queue identified by the +queue_name+. Not designed to be used directly, this
|
13
14
|
# method ferries to the publish method on an instance of your configured Publisher.
|
15
|
+
#
|
16
|
+
# @param [String] queue_name Name of queue to be consumed from
|
17
|
+
# @param [Hash] job Job instance definition, will be encoded to JSON
|
14
18
|
def self.publish(queue_name,job)
|
15
19
|
self.new.publish(queue_name,job)
|
16
20
|
end
|
17
21
|
|
18
|
-
#
|
22
|
+
# Publishes a message to queue
|
23
|
+
#
|
24
|
+
# @param [String] queue_name Name of the SQS queue
|
25
|
+
# @param [Hash] job Job instance definition, will be encoded to JSON
|
19
26
|
def publish(queue_name,job)
|
20
27
|
raise NotImplementedError
|
21
28
|
end
|
29
|
+
|
30
|
+
# Sets a flag that instructs the publisher to reset the connection the next time it's used.
|
31
|
+
# Should be overriden in publishers (but is not required)
|
32
|
+
def self.reset_connection!
|
33
|
+
end
|
34
|
+
|
22
35
|
protected
|
23
36
|
|
37
|
+
# Encodes the job class to format provided by endoder implementation
|
38
|
+
#
|
39
|
+
# @param [Any] job
|
24
40
|
def encode_job(job)
|
25
41
|
options[:encoder].encode(job)
|
26
42
|
end
|