batsir 0.1.0 → 0.3.7
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.
- data/.travis.yml +9 -1
- data/CHANGES.md +54 -0
- data/Gemfile +7 -10
- data/README.md +49 -5
- data/Rakefile +23 -16
- data/batsir.gemspec +43 -15
- data/lib/batsir/acceptors/acceptor.rb +31 -5
- data/lib/batsir/acceptors/amqp_acceptor.rb +36 -8
- data/lib/batsir/amqp.rb +35 -7
- data/lib/batsir/amqp_consumer.rb +8 -0
- data/lib/batsir/compiler/stage_worker_compiler.rb +86 -0
- data/lib/batsir/config.rb +208 -24
- data/lib/batsir/dsl/conditional_notifier_declaration.rb +31 -0
- data/lib/batsir/dsl/dsl_mappings.rb +27 -2
- data/lib/batsir/errors.rb +18 -0
- data/lib/batsir/filter.rb +5 -0
- data/lib/batsir/log.rb +7 -0
- data/lib/batsir/logger.rb +37 -0
- data/lib/batsir/logo.rb +3 -8
- data/lib/batsir/notifiers/amqp_notifier.rb +14 -4
- data/lib/batsir/notifiers/conditional_notifier.rb +29 -0
- data/lib/batsir/notifiers/notifier.rb +6 -5
- data/lib/batsir/registry.rb +6 -2
- data/lib/batsir/stage.rb +9 -4
- data/lib/batsir/stage_worker.rb +3 -56
- data/lib/batsir/strategies/retry_strategy.rb +35 -0
- data/lib/batsir/strategies/strategy.rb +20 -0
- data/lib/batsir/transformers/field_transformer.rb +2 -3
- data/lib/batsir/transformers/json_input_transformer.rb +6 -2
- data/lib/batsir/transformers/json_output_transformer.rb +6 -2
- data/lib/batsir/transformers/transformer.rb +5 -1
- data/lib/batsir/version.rb +10 -0
- data/lib/batsir.rb +31 -13
- data/spec/batsir/acceptors/acceptor_spec.rb +7 -78
- data/spec/batsir/acceptors/amqp_acceptor_spec.rb +55 -66
- data/spec/batsir/acceptors/shared_examples.rb +102 -0
- data/spec/batsir/amqp_spec.rb +58 -0
- data/spec/batsir/chain_spec.rb +4 -4
- data/spec/batsir/config_spec.rb +97 -0
- data/spec/batsir/dsl/chain_mapping_spec.rb +5 -6
- data/spec/batsir/dsl/conditional_notifier_mapping_spec.rb +80 -0
- data/spec/batsir/dsl/stage_mapping_spec.rb +38 -20
- data/spec/batsir/filter_queue_spec.rb +9 -15
- data/spec/batsir/filter_spec.rb +4 -5
- data/spec/batsir/log_spec.rb +10 -0
- data/spec/batsir/logger_spec.rb +46 -0
- data/spec/batsir/notifiers/amqp_notifier_spec.rb +43 -22
- data/spec/batsir/notifiers/conditional_notifier_spec.rb +62 -0
- data/spec/batsir/notifiers/notifier_spec.rb +4 -66
- data/spec/batsir/notifiers/shared_examples.rb +100 -0
- data/spec/batsir/registry_spec.rb +48 -0
- data/spec/batsir/stage_spec.rb +91 -85
- data/spec/batsir/stage_worker_spec.rb +13 -13
- data/spec/batsir/strategies/retry_strategy_spec.rb +58 -0
- data/spec/batsir/strategies/strategy_spec.rb +28 -0
- data/spec/batsir/support/bunny_mocks.rb +78 -5
- data/spec/batsir/transformers/field_transformer_spec.rb +22 -22
- data/spec/batsir/transformers/json_input_transformer_spec.rb +8 -3
- data/spec/batsir/transformers/json_output_transformer_spec.rb +2 -2
- data/spec/batsir/transformers/transformer_spec.rb +18 -4
- data/spec/spec_helper.rb +6 -2
- metadata +78 -23
- data/VERSION +0 -1
data/lib/batsir/config.rb
CHANGED
@@ -1,34 +1,218 @@
|
|
1
1
|
module Batsir
|
2
2
|
class Config
|
3
|
-
|
4
|
-
@data = {}
|
5
|
-
update!(data)
|
6
|
-
end
|
3
|
+
class << self
|
7
4
|
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
# Adapted from Merb::Config class
|
6
|
+
|
7
|
+
attr_accessor :config
|
8
|
+
|
9
|
+
def defaults
|
10
|
+
@defaults ||= {
|
11
|
+
:amqp_host => 'localhost',
|
12
|
+
:amqp_port => 5672,
|
13
|
+
:amqp_user => 'guest',
|
14
|
+
:amqp_pass => 'guest',
|
15
|
+
:amqp_vhost => '/',
|
16
|
+
:amqp_durable => true,
|
17
|
+
:ampq_pool_size => 5,
|
18
|
+
:redis_host => 'localhost',
|
19
|
+
:redis_port => 6379,
|
20
|
+
:redis_database => 0,
|
21
|
+
:redis_namespace => 'batsir',
|
22
|
+
:sidekiq_queue => 'batsir',
|
23
|
+
:log_name => 'batsir'
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the current configuration or sets it up
|
28
|
+
def configuration
|
29
|
+
@config ||= setup
|
30
|
+
end
|
31
|
+
|
32
|
+
# Yields the configuration.
|
33
|
+
#
|
34
|
+
# ==== Block parameters
|
35
|
+
# c<Hash>:: The configuration parameters.
|
36
|
+
#
|
37
|
+
# ==== Examples
|
38
|
+
# Batsir::Config.use do |config|
|
39
|
+
# config[:exception_details] = false
|
40
|
+
# config[:log_stream] = STDOUT
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# ==== Returns
|
44
|
+
# nil
|
45
|
+
#
|
46
|
+
# :api: public
|
47
|
+
def use
|
48
|
+
yield configuration
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# Detects whether the provided key is in the config.
|
53
|
+
#
|
54
|
+
# ==== Parameters
|
55
|
+
# key<Object>:: The key to check.
|
56
|
+
#
|
57
|
+
# ==== Returns
|
58
|
+
# Boolean:: True if the key exists in the config.
|
59
|
+
#
|
60
|
+
# :api: public
|
61
|
+
def key?(key)
|
62
|
+
configuration.key?(key)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Retrieve the value of a config entry.
|
66
|
+
#
|
67
|
+
# ==== Parameters
|
68
|
+
# key<Object>:: The key to retrieve the parameter for.
|
69
|
+
#
|
70
|
+
# ==== Returns
|
71
|
+
# Object:: The value of the configuration parameter.
|
72
|
+
#
|
73
|
+
# :api: public
|
74
|
+
def [](key)
|
75
|
+
configuration[key]
|
76
|
+
end
|
77
|
+
|
78
|
+
# Set the value of a config entry.
|
79
|
+
#
|
80
|
+
# ==== Parameters
|
81
|
+
# key<Object>:: The key to set the parameter for.
|
82
|
+
# val<Object>:: The value of the parameter.
|
83
|
+
#
|
84
|
+
# :api: public
|
85
|
+
def []=(key, val)
|
86
|
+
configuration[key] = val
|
87
|
+
end
|
88
|
+
|
89
|
+
# Remove the value of a config entry.
|
90
|
+
#
|
91
|
+
# ==== Parameters
|
92
|
+
# key<Object>:: The key of the parameter to delete.
|
93
|
+
#
|
94
|
+
# ==== Returns
|
95
|
+
# Object:: The value of the removed entry.
|
96
|
+
#
|
97
|
+
# :api: public
|
98
|
+
def delete(key)
|
99
|
+
configuration.delete(key)
|
11
100
|
end
|
12
|
-
end
|
13
101
|
|
14
|
-
|
15
|
-
|
16
|
-
|
102
|
+
# Resets the configuration to its default state
|
103
|
+
#
|
104
|
+
def reset
|
105
|
+
setup
|
106
|
+
end
|
107
|
+
|
108
|
+
# Retrieve the value of a config entry, returning the provided default if the key is not present
|
109
|
+
#
|
110
|
+
# ==== Parameters
|
111
|
+
# key<Object>:: The key to retrieve the parameter for.
|
112
|
+
# default<Object>::
|
113
|
+
# The default value to return if the parameter is not set.
|
114
|
+
#
|
115
|
+
# ==== Returns
|
116
|
+
# Object:: The value of the configuration parameter or the default.
|
117
|
+
#
|
118
|
+
# :api: public
|
119
|
+
def fetch(key, default = nil)
|
120
|
+
configuration.fetch(key, default)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns the configuration as a hash.
|
124
|
+
#
|
125
|
+
# ==== Returns
|
126
|
+
# Hash:: The config as a hash.
|
127
|
+
#
|
128
|
+
# :api: public
|
129
|
+
def to_hash
|
130
|
+
configuration
|
131
|
+
end
|
132
|
+
|
133
|
+
# Sets up the configuration by storing the given settings.
|
134
|
+
#
|
135
|
+
# ==== Parameters
|
136
|
+
# settings<Hash>::
|
137
|
+
# Configuration settings to use. These are merged with the defaults.
|
138
|
+
#
|
139
|
+
# ==== Returns
|
140
|
+
# The configuration as a hash.
|
141
|
+
#
|
142
|
+
# :api: private
|
143
|
+
def setup(settings = {})
|
144
|
+
@config = defaults.merge(settings)
|
145
|
+
end
|
17
146
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
147
|
+
# Set configuration parameters from a code block, where each method
|
148
|
+
# evaluates to a config parameter.
|
149
|
+
#
|
150
|
+
# ==== Parameters
|
151
|
+
# &block:: Configuration parameter block.
|
152
|
+
#
|
153
|
+
# ==== Examples
|
154
|
+
# # Set environment and log level.
|
155
|
+
# Batsir::Config.configure do
|
156
|
+
# environment "development"
|
157
|
+
# log_level "debug"
|
158
|
+
# end
|
159
|
+
#
|
160
|
+
# ==== Returns
|
161
|
+
# nil
|
162
|
+
#
|
163
|
+
# :api: public
|
164
|
+
def configure(&block)
|
165
|
+
ConfigBlock.new(self, &block) if block_given?
|
166
|
+
nil
|
23
167
|
end
|
24
|
-
end
|
25
168
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
169
|
+
# Allows retrieval of single key config values via Batsir::Config.<key>
|
170
|
+
# Allows single key assignment via Merb.config.<key> = ...
|
171
|
+
#
|
172
|
+
# ==== Parameters
|
173
|
+
# method<~to_s>:: Method name as hash key value.
|
174
|
+
# *args:: Value to set the configuration parameter to.
|
175
|
+
#
|
176
|
+
# ==== Returns
|
177
|
+
# The value of the entry fetched or assigned to.
|
178
|
+
#
|
179
|
+
# :api: public
|
180
|
+
def method_missing(method, *args)
|
181
|
+
if method.to_s[-1,1] == '='
|
182
|
+
self[method.to_s.tr('=','').to_sym] = args.first
|
183
|
+
else
|
184
|
+
self[method]
|
185
|
+
end
|
31
186
|
end
|
32
|
-
|
33
|
-
|
187
|
+
|
188
|
+
end # class << self
|
189
|
+
|
190
|
+
class ConfigBlock
|
191
|
+
|
192
|
+
# Evaluates the provided block, where any call to a method causes
|
193
|
+
# #[]= to be called on klass with the method name as the key and the arguments
|
194
|
+
# as the value.
|
195
|
+
#
|
196
|
+
# ==== Parameters
|
197
|
+
# klass<Object~[]=>:: The object on which to assign values.
|
198
|
+
# &block:: The block which specifies the config values to set.
|
199
|
+
#
|
200
|
+
# ==== Returns
|
201
|
+
# nil
|
202
|
+
#
|
203
|
+
# :api: private
|
204
|
+
def initialize(klass, &block)
|
205
|
+
@klass = klass
|
206
|
+
instance_eval(&block)
|
207
|
+
end
|
208
|
+
|
209
|
+
# Assign args as the value of the entry keyed by method.
|
210
|
+
#
|
211
|
+
# :api: private
|
212
|
+
def method_missing(method, *args)
|
213
|
+
@klass[method] = args.first
|
214
|
+
end
|
215
|
+
|
216
|
+
end # ConfigBlock
|
217
|
+
end # Config
|
34
218
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Batsir
|
2
|
+
module DSL
|
3
|
+
class ConditionalNotifierDeclaration
|
4
|
+
attr_reader :notifier_declarations
|
5
|
+
|
6
|
+
NotifierConditionDeclaration = Struct.new(:condition, :notifier, :options)
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@notifier_declarations = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_conditional(condition, notifier_class, options)
|
13
|
+
@notifier_declarations << NotifierConditionDeclaration.new(condition, notifier_class, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def compile(output, stage_worker)
|
17
|
+
output << <<-EOF
|
18
|
+
conditional_notifier = Batsir::Notifiers::ConditionalNotifier.new
|
19
|
+
EOF
|
20
|
+
notifier_declarations.each do |notifier_declaration|
|
21
|
+
output << <<-EOF
|
22
|
+
condition = ->(message){#{notifier_declaration.condition}}
|
23
|
+
conditional_notifier.add_notifier condition, #{notifier_declaration.notifier}.new(#{notifier_declaration.options.to_s})
|
24
|
+
EOF
|
25
|
+
end
|
26
|
+
stage_worker.add_transformers_to_notifier("conditional_notifier", output)
|
27
|
+
stage_worker.add_notifier( "conditional_notifier", output)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -32,8 +32,8 @@ module Batsir
|
|
32
32
|
@stage
|
33
33
|
end
|
34
34
|
|
35
|
-
def filter(
|
36
|
-
@stage.add_filter(
|
35
|
+
def filter(filter_class, options = {})
|
36
|
+
@stage.add_filter(filter_class, options)
|
37
37
|
end
|
38
38
|
|
39
39
|
def inbound(&block)
|
@@ -43,6 +43,7 @@ module Batsir
|
|
43
43
|
def outbound(&block)
|
44
44
|
::Blockenspiel.invoke(block, Batsir::DSL::OutboundMapping.new(@stage))
|
45
45
|
end
|
46
|
+
|
46
47
|
end
|
47
48
|
|
48
49
|
class InboundMapping < ::Blockenspiel::Base
|
@@ -78,6 +79,14 @@ module Batsir
|
|
78
79
|
::Blockenspiel.invoke(block, Batsir::DSL::OutboundTransformerMapping.new(@stage))
|
79
80
|
end
|
80
81
|
|
82
|
+
def conditional(&block)
|
83
|
+
new_block = ::Proc.new do
|
84
|
+
conditional &block
|
85
|
+
end
|
86
|
+
conditional = ::Blockenspiel.invoke(new_block, Batsir::DSL::ConditionalNotifierMapping.new)
|
87
|
+
@stage.add_conditional_notifier(conditional)
|
88
|
+
end
|
89
|
+
|
81
90
|
def notifier(notifier_class, options = {})
|
82
91
|
@stage.add_notifier(notifier_class, options)
|
83
92
|
end
|
@@ -92,5 +101,21 @@ module Batsir
|
|
92
101
|
@stage.add_notifier_transformer(transformer, options)
|
93
102
|
end
|
94
103
|
end
|
104
|
+
|
105
|
+
class ConditionalNotifierMapping < ::Blockenspiel::Base
|
106
|
+
def initialize
|
107
|
+
@notifier = nil
|
108
|
+
end
|
109
|
+
|
110
|
+
def conditional(&block)
|
111
|
+
@notifier = Batsir::DSL::ConditionalNotifierDeclaration.new
|
112
|
+
::Blockenspiel.invoke(block, self)
|
113
|
+
@notifier
|
114
|
+
end
|
115
|
+
|
116
|
+
def notify_if(condition, notifier, options = {})
|
117
|
+
@notifier.add_conditional(condition, notifier, options)
|
118
|
+
end
|
119
|
+
end
|
95
120
|
end
|
96
121
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Batsir
|
2
|
+
module Errors
|
3
|
+
|
4
|
+
class BatsirError < RuntimeError; end
|
5
|
+
class NotifierError < BatsirError; end
|
6
|
+
class TransformError < BatsirError; end
|
7
|
+
class StrategyError < BatsirError; end
|
8
|
+
|
9
|
+
class ExecuteMethodNotImplementedError < BatsirError; end
|
10
|
+
|
11
|
+
class NotifierConnectionError < NotifierError; end
|
12
|
+
|
13
|
+
class JSONInputTransformError < TransformError; end
|
14
|
+
class JSONOutputTransformError < TransformError; end
|
15
|
+
|
16
|
+
class RetryStrategyFailed < StrategyError; end
|
17
|
+
end
|
18
|
+
end
|
data/lib/batsir/filter.rb
CHANGED
data/lib/batsir/log.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
|
3
|
+
module Batsir
|
4
|
+
module Logger
|
5
|
+
DEBUG = 1
|
6
|
+
INFO = 2
|
7
|
+
WARN = 3
|
8
|
+
ERROR = 4
|
9
|
+
FATAL = 5
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
DEFAULT_OUTPUT = 'stdout'
|
14
|
+
|
15
|
+
def log
|
16
|
+
@logger ||= setup
|
17
|
+
end
|
18
|
+
|
19
|
+
def setup
|
20
|
+
logger = Log4r::Logger.new(Batsir::Config.fetch(:log_name, "batsir"))
|
21
|
+
logger.level = Batsir::Config.fetch(:log_level, WARN)
|
22
|
+
logger.outputters = Batsir::Config.fetch(:log_outputter, DEFAULT_OUTPUT)
|
23
|
+
logger
|
24
|
+
end
|
25
|
+
|
26
|
+
def reset
|
27
|
+
@logger = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# makes this respond like a Log4r::Logger
|
31
|
+
def method_missing(sym, *args, &block)
|
32
|
+
log.send sym, *args, &block
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/batsir/logo.rb
CHANGED
@@ -2,10 +2,6 @@ module Batsir
|
|
2
2
|
def self.logo
|
3
3
|
<<EOF
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
5
|
E ,.
|
10
6
|
,,,agB8@f ,8v ,8L J88&gg,,,
|
11
7
|
.,a88888888@^ |8&,,,,,,88k ,88888888&g,,
|
@@ -26,10 +22,9 @@ module Batsir
|
|
26
22
|
`?9@888&, j88f ,d88$@9l'
|
27
23
|
`|?9t |f `9T"`
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
______ _______ _______ _______ _____ ______
|
26
|
+
|_____] |_____| | |______ | |_____/
|
27
|
+
|_____] | | | ______| __|__ | \\_
|
33
28
|
|
34
29
|
EOF
|
35
30
|
end
|
@@ -5,11 +5,21 @@ module Batsir
|
|
5
5
|
class AMQPNotifier < Notifier
|
6
6
|
include Batsir::AMQP
|
7
7
|
|
8
|
+
attr_reader :error_strategy
|
9
|
+
|
10
|
+
def initialize(options = {}, error_strategy = Batsir::Strategies::RetryStrategy)
|
11
|
+
super(options)
|
12
|
+
@error_strategy = error_strategy.new(self)
|
13
|
+
@bunny = Bunny.new(bunny_options).start
|
14
|
+
@x = @bunny.exchange( exchange )
|
15
|
+
end
|
16
|
+
|
8
17
|
def execute(message)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
18
|
+
@x.publish(message, :routing_key => queue)
|
19
|
+
end
|
20
|
+
|
21
|
+
def handle_error(message, error)
|
22
|
+
@error_strategy.execute(message, error)
|
13
23
|
end
|
14
24
|
end
|
15
25
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Batsir
|
2
|
+
module Notifiers
|
3
|
+
class ConditionalNotifier < Notifier
|
4
|
+
attr_accessor :notifiers
|
5
|
+
|
6
|
+
NotifierCondition = Struct.new(:condition, :notifier, :options)
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
super
|
10
|
+
@notifiers = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_notifier( condition, notifier_class, options = {})
|
14
|
+
self.notifiers << NotifierCondition.new(condition, notifier_class, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute(message)
|
18
|
+
self.notifiers.each do |notifier_condition|
|
19
|
+
if notifier_condition.condition.call(message)
|
20
|
+
notifier = notifier_condition.notifier
|
21
|
+
options = notifier_condition.options
|
22
|
+
notifier.notify(message)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
message
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -21,11 +21,8 @@ module Batsir
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def notify(message)
|
24
|
-
execute(transform(message))
|
25
|
-
|
26
|
-
|
27
|
-
def execute(message)
|
28
|
-
|
24
|
+
execute(transform(message.clone))
|
25
|
+
message
|
29
26
|
end
|
30
27
|
|
31
28
|
def transform(message)
|
@@ -34,6 +31,10 @@ module Batsir
|
|
34
31
|
end
|
35
32
|
message
|
36
33
|
end
|
34
|
+
|
35
|
+
def execute(message)
|
36
|
+
raise NotImplementedError.new
|
37
|
+
end
|
37
38
|
end
|
38
39
|
end
|
39
40
|
end
|
data/lib/batsir/registry.rb
CHANGED
data/lib/batsir/stage.rb
CHANGED
@@ -10,6 +10,7 @@ module Batsir
|
|
10
10
|
attr_accessor :cancellators
|
11
11
|
attr_reader :filter_declarations
|
12
12
|
attr_reader :notifiers
|
13
|
+
attr_reader :conditional_notifiers
|
13
14
|
attr_reader :acceptors
|
14
15
|
attr_reader :running_acceptors
|
15
16
|
attr_reader :notifier_transformers
|
@@ -25,6 +26,7 @@ module Batsir
|
|
25
26
|
@acceptors = {}
|
26
27
|
@filter_declarations = []
|
27
28
|
@notifiers = {}
|
29
|
+
@conditional_notifiers = []
|
28
30
|
@notifier_transformers = []
|
29
31
|
@built = false
|
30
32
|
end
|
@@ -50,6 +52,10 @@ module Batsir
|
|
50
52
|
@filter_declarations.map{ |filter_declaration| filter_declaration.filter }
|
51
53
|
end
|
52
54
|
|
55
|
+
def add_conditional_notifier(notifier_declaration)
|
56
|
+
@conditional_notifiers << notifier_declaration
|
57
|
+
end
|
58
|
+
|
53
59
|
def add_notifier(notifier, options = {})
|
54
60
|
@notifiers[notifier] ||= Set.new
|
55
61
|
@notifiers[notifier] << options
|
@@ -72,10 +78,9 @@ module Batsir
|
|
72
78
|
def start
|
73
79
|
acceptors.each do |acceptor_class, options|
|
74
80
|
options.each do |acceptor_options|
|
75
|
-
|
76
|
-
acceptor_options.merge!(:stage_name => self.name, :cancellator => cancellator_reader)
|
77
|
-
@cancellators << cancellator_writer
|
81
|
+
acceptor_options.merge!(:stage_name => self.name)
|
78
82
|
acceptor = acceptor_class.new(acceptor_options)
|
83
|
+
|
79
84
|
if acceptor_transformers.any?
|
80
85
|
acceptor_transformers.each do |transformer_declaration|
|
81
86
|
transformer = transformer_declaration.transformer.new(transformer_declaration.options)
|
@@ -85,7 +90,7 @@ module Batsir
|
|
85
90
|
acceptor.add_transformer(Batsir::Transformers::JSONInputTransformer.new)
|
86
91
|
end
|
87
92
|
@running_acceptors << acceptor
|
88
|
-
acceptor.start
|
93
|
+
acceptor.async.start
|
89
94
|
end
|
90
95
|
end
|
91
96
|
true
|
data/lib/batsir/stage_worker.rb
CHANGED
@@ -14,9 +14,10 @@ module Batsir
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def execute(message)
|
17
|
+
return false if message.nil?
|
17
18
|
return false unless @filter_queue
|
18
19
|
@filter_queue.filters.each do |filter|
|
19
|
-
message = filter.
|
20
|
+
message = filter.filter(message)
|
20
21
|
return false if message.nil?
|
21
22
|
end
|
22
23
|
@filter_queue.notifiers.each do |notifier|
|
@@ -26,61 +27,7 @@ module Batsir
|
|
26
27
|
end
|
27
28
|
|
28
29
|
def self.compile_from(stage)
|
29
|
-
|
30
|
-
class #{stage.name.capitalize.gsub(' ','')}Worker
|
31
|
-
def self.stage_name
|
32
|
-
"#{stage.name}"
|
33
|
-
end
|
34
|
-
|
35
|
-
def initialize
|
36
|
-
@filter_queue = self.class.filter_queue
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.filter_queue
|
40
|
-
@filter_queue
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.initialize_filter_queue
|
44
|
-
@filter_queue = Batsir::FilterQueue.new
|
45
|
-
EOF
|
46
|
-
|
47
|
-
stage.filter_declarations.each do |filter_declaration|
|
48
|
-
code << <<-EOF
|
49
|
-
@filter_queue.add #{filter_declaration.filter.to_s}.new(#{filter_declaration.options.to_s})
|
50
|
-
EOF
|
51
|
-
end
|
52
|
-
|
53
|
-
stage.notifiers.each do |notifier, options_set|
|
54
|
-
options_set.each do |options|
|
55
|
-
code << <<-EOF
|
56
|
-
notifier = #{notifier.to_s}.new(#{options.to_s})
|
57
|
-
EOF
|
58
|
-
|
59
|
-
if stage.notifier_transformers.any?
|
60
|
-
stage.notifier_transformers.each do |transformer_declaration|
|
61
|
-
code << <<-EOF
|
62
|
-
notifier.add_transformer #{transformer_declaration.transformer}.new(#{transformer_declaration.options.to_s})
|
63
|
-
EOF
|
64
|
-
end
|
65
|
-
else
|
66
|
-
code << <<-EOF
|
67
|
-
notifier.add_transformer Batsir::Transformers::JSONOutputTransformer.new
|
68
|
-
EOF
|
69
|
-
end
|
70
|
-
code << <<-EOF
|
71
|
-
@filter_queue.add_notifier notifier
|
72
|
-
EOF
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
code << <<-EOF
|
77
|
-
end
|
78
|
-
|
79
|
-
include Sidekiq::Worker
|
80
|
-
include Batsir::StageWorker
|
81
|
-
end
|
82
|
-
EOF
|
83
|
-
code
|
30
|
+
Batsir::Compiler::StageWorkerCompiler.new(stage).compile
|
84
31
|
end
|
85
32
|
end
|
86
33
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Batsir
|
2
|
+
module Strategies
|
3
|
+
class RetryStrategy < Strategy
|
4
|
+
include Batsir::Log
|
5
|
+
|
6
|
+
attr_reader :retries, :attempts
|
7
|
+
|
8
|
+
def initialize(context, retries = 3)
|
9
|
+
super(context)
|
10
|
+
@retries = retries
|
11
|
+
@attempts = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute(message, error)
|
15
|
+
@attempts[message] ? @attempts[message] += 1 : @attempts[message] = 0
|
16
|
+
|
17
|
+
if @attempts[message] >= @retries
|
18
|
+
error_msg = "Tried to send '#{message}' #{@attempts[message]} times and failed"
|
19
|
+
reset_attempts(message)
|
20
|
+
log.error error_msg
|
21
|
+
raise Batsir::Errors::RetryStrategyFailed.new error_msg
|
22
|
+
else
|
23
|
+
log.warn "Recovering from #{error}. Making another attempt (##{@attempts[message]+1})"
|
24
|
+
result = @context.execute(message)
|
25
|
+
reset_attempts(message)
|
26
|
+
return result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def reset_attempts(message)
|
31
|
+
@attempts.delete(message)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|