tochtli 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 56acd327a8d04ef8de6ca2ab8a2b677e27e276e4
4
- data.tar.gz: c0f076e6906b0ef7a401585be0946ec1b8b0d1f3
3
+ metadata.gz: d7a4aeafb78f7399f7f0f7444bcae42b8a025fa6
4
+ data.tar.gz: 5d387cebbd67b3323ee3ef60e7f2eac1d6cc7087
5
5
  SHA512:
6
- metadata.gz: 4653fc71fcd32d2a9a21bb9929d9994564b2b3b5e1a680e04faf414705ad7bf9b9bcc8e12e274d653183f2fec2780adb3d872a93c004123c611820479d95cd97
7
- data.tar.gz: 4e799d6d4888f1182772ca63dfdcd534fa2255f50926a98bb2a3df8ba1fd0b5b8b897361227e785dfdb5287269400ecac5cae7be9925f6cd2babf2350889fdb9
6
+ metadata.gz: 556377482683580c625cbf00a34f100bbf03fd8a0c3338b7f6a10efba216283d27be4389dca208168a47923ea08dd72f68710bddafd2271c60c32a3f83100bd0
7
+ data.tar.gz: c7b5e7dee6939180abe8981e110c87d02e62fefa223971f32aa46bd27ce72ddb7fa605bf944ca7107f1f3cf52ba9f8638195ec687327461243768a0302c4f572
data/History.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.5.1 / 2015-08-19
2
+
3
+ * [Integration Tests] Fix controller manager restart - some controllers are fixed to the test connection after functional tests
4
+
1
5
  ## 0.5.0 / 2015-08-19
2
6
 
3
7
  * Usage examples
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  [![Build Status](https://travis-ci.org/PuzzleFlow/tochtli.svg?branch=master)](https://travis-ci.org/PuzzleFlow/tochtli)
2
+ [![Gem Version](https://badge.fury.io/rb/tochtli.svg)](http://badge.fury.io/rb/tochtli)
2
3
 
3
4
  # What's Tochtli?
4
5
 
@@ -43,4 +44,4 @@ Read more about Tochtli and go through the tutorial on [Tochtli homepage](http:/
43
44
 
44
45
  # License
45
46
 
46
- Released under the MIT license.
47
+ Released under the MIT license.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.5.1
@@ -3,13 +3,13 @@ require_relative 'common'
3
3
  Tochtli.logger.progname = 'CLIENT'
4
4
 
5
5
  class ScreenerClient < Tochtli::BaseClient
6
- def create_screen(url, file_name)
7
- handler = SyncMessageHandler.new
8
- message = CreateScreenMessage.new(url: url, file: file_name)
9
- rabbit_client.publish message, handler: handler
10
- handler.wait!(20)
11
- puts "Done in #{handler.reply.time} seconds"
12
- end
6
+ def create_screen(url, file_name)
7
+ handler = SyncMessageHandler.new
8
+ message = CreateScreenMessage.new(url: url, file: file_name)
9
+ rabbit_client.publish message, handler: handler
10
+ handler.wait!(20)
11
+ puts "Done in #{handler.reply.time} seconds"
12
+ end
13
13
  end
14
14
 
15
15
  ScreenerClient.new.create_screen(ARGV[0], ARGV[1])
@@ -4,12 +4,12 @@ Bundler.require
4
4
  Tochtli.logger = Logger.new('tochtli.log')
5
5
 
6
6
  class CreateScreenMessage < Tochtli::Message
7
- route_to 'screener.create'
7
+ route_to 'screener.create'
8
8
 
9
- attribute :url, String
10
- attribute :file, String
9
+ attribute :url, String
10
+ attribute :file, String
11
11
  end
12
12
 
13
13
  class CreateScreenReplyMessage < Tochtli::Message
14
- attribute :time, Float
14
+ attribute :time, Float
15
15
  end
@@ -3,17 +3,17 @@ require_relative 'common'
3
3
  Tochtli.logger.progname = 'SERVER'
4
4
 
5
5
  class ScreenerController < Tochtli::BaseController
6
- bind 'screener.*'
6
+ bind 'screener.*'
7
7
 
8
- on CreateScreenMessage, :create
8
+ on CreateScreenMessage, :create
9
9
 
10
- def create
11
- start_time = Time.now
12
- f = Screencap::Fetcher.new(message.url)
13
- f.fetch output: File.join(__dir__, 'images', message.file)
14
- total_time = Time.now - start_time
15
- reply CreateScreenReplyMessage.new(time: total_time)
16
- end
10
+ def create
11
+ start_time = Time.now
12
+ f = Screencap::Fetcher.new(message.url)
13
+ f.fetch output: File.join(__dir__, 'images', message.file)
14
+ total_time = Time.now - start_time
15
+ reply CreateScreenReplyMessage.new(time: total_time)
16
+ end
17
17
  end
18
18
 
19
19
  Tochtli::ControllerManager.setup
@@ -9,9 +9,9 @@ module LogAnalyzer
9
9
  end
10
10
 
11
11
  def react_on_events(client_id, severities, handler=nil, &block)
12
- handler = block unless handler
12
+ handler = block unless handler
13
13
  severities = Array(severities)
14
- routing_keys = severities.map {|severity| "log.events.#{severity}" }
14
+ routing_keys = severities.map {|severity| "log.events.#{severity}" }
15
15
  Tochtli::ControllerManager.start EventsController,
16
16
  queue_name: "log_analyzer/events/#{client_id}", # custom queue name
17
17
  routing_keys: routing_keys, # make custom binding (only selected severities)
@@ -19,7 +19,7 @@ module LogAnalyzer
19
19
  end
20
20
 
21
21
  def monitor_status(monitor=nil, &block)
22
- monitor = block unless monitor
22
+ monitor = block unless monitor
23
23
  Tochtli::ControllerManager.start MonitorController, env: { monitor: monitor }
24
24
  end
25
25
  end
@@ -27,18 +27,18 @@ module LogAnalyzer
27
27
  protected
28
28
 
29
29
  class EventsController < Tochtli::BaseController
30
- on EventOccurred, :handle, routing_key: 'log.events.*'
30
+ on EventOccurred, :handle, routing_key: 'log.events.*'
31
31
 
32
32
  def handle
33
- handler.call(message.severity, message.timestamp, message.message)
33
+ handler.call(message.severity, message.timestamp, message.message)
34
34
  end
35
35
 
36
- protected
36
+ protected
37
37
 
38
- def handler
39
- raise "Internal Error: handler not set for EventsController" unless env.has_key?(:handler)
40
- env[:handler]
41
- end
38
+ def handler
39
+ raise "Internal Error: handler not set for EventsController" unless env.has_key?(:handler)
40
+ env[:handler]
41
+ end
42
42
  end
43
43
 
44
44
  class MonitorController < Tochtli::BaseController
@@ -50,14 +50,14 @@ module LogAnalyzer
50
50
  self.queue_auto_delete = true
51
51
 
52
52
  on CurrentStatus do
53
- monitor.call(message.to_hash)
53
+ monitor.call(message.to_hash)
54
54
  end
55
55
 
56
56
  protected
57
57
 
58
58
  def monitor
59
- raise "Internal Error: monitor not set for MonitorController" unless env.has_key?(:monitor)
60
- env[:monitor]
59
+ raise "Internal Error: monitor not set for MonitorController" unless env.has_key?(:monitor)
60
+ env[:monitor]
61
61
  end
62
62
  end
63
63
  end
@@ -66,30 +66,30 @@ client = LogAnalyzer::Client.new
66
66
  command = ARGV[0]
67
67
 
68
68
  def hold
69
- puts 'Press Ctrl-C to stop...'
70
- sleep
69
+ puts 'Press Ctrl-C to stop...'
70
+ sleep
71
71
  end
72
72
 
73
73
 
74
74
  case command
75
- when 's'
76
- client.send_new_log ARGV[1]
77
- when 'm'
78
- client.monitor_status {|status| p status }
79
- hold
80
- when 'c'
81
- client.react_on_events ARGV[1], [:fatal, :error], lambda {|severity, timestamp, message|
82
- puts "[#{timestamp}] Got #{severity}: #{message}"
83
- }
84
- hold
85
- else
86
- puts "Unknown command: #{command.inspect}"
87
- puts
88
- puts "Usage: bundle exec ruby client [command] [params]"
89
- puts
90
- puts "Commands:"
91
- puts " s [path] - send log from file to server"
92
- puts " m - start status monitor"
93
- puts " c [client ID] - catch fatal and error events"
75
+ when 's'
76
+ client.send_new_log ARGV[1]
77
+ when 'm'
78
+ client.monitor_status {|status| p status }
79
+ hold
80
+ when 'c'
81
+ client.react_on_events ARGV[1], [:fatal, :error], lambda {|severity, timestamp, message|
82
+ puts "[#{timestamp}] Got #{severity}: #{message}"
83
+ }
84
+ hold
85
+ else
86
+ puts "Unknown command: #{command.inspect}"
87
+ puts
88
+ puts "Usage: bundle exec ruby client [command] [params]"
89
+ puts
90
+ puts "Commands:"
91
+ puts " s [path] - send log from file to server"
92
+ puts " m - start status monitor"
93
+ puts " c [client ID] - catch fatal and error events"
94
94
  end
95
95
 
@@ -14,8 +14,8 @@ module LogAnalyzer
14
14
  cattr_accessor :monitor
15
15
 
16
16
  after_setup do |rabbit_connection|
17
- self.monitor = StatusMonitor.new(rabbit_connection)
18
- self.monitor.start
17
+ self.monitor = StatusMonitor.new(rabbit_connection)
18
+ self.monitor.start
19
19
  end
20
20
 
21
21
  def create
@@ -68,11 +68,11 @@ module LogAnalyzer
68
68
  end
69
69
 
70
70
  class EventNotifier < Tochtli::BaseClient
71
- SIGNIFICANT_SEVERITIES = [:fatal, :error, :warn]
71
+ SIGNIFICANT_SEVERITIES = [:fatal, :error, :warn]
72
72
 
73
- def self.significant?(severity)
74
- SIGNIFICANT_SEVERITIES.include?(severity)
75
- end
73
+ def self.significant?(severity)
74
+ SIGNIFICANT_SEVERITIES.include?(severity)
75
+ end
76
76
 
77
77
  def notify(event)
78
78
  publish EventOccurred.new(event), mandatory: false
@@ -105,18 +105,18 @@ module LogAnalyzer
105
105
  protected
106
106
 
107
107
  def reset_status
108
- synchronize do
109
- status = @status
110
- @status = Hash.new(0)
111
- status
112
- end
108
+ synchronize do
109
+ status = @status
110
+ @status = Hash.new(0)
111
+ status
112
+ end
113
113
  end
114
114
 
115
115
  def monitor
116
116
  loop do
117
117
  current_status = reset_status
118
118
  current_status[:timestamp] = Time.now
119
- @notifier.update_status current_status
119
+ @notifier.update_status current_status
120
120
  sleep 10
121
121
  end
122
122
  end
@@ -69,9 +69,9 @@ module Tochtli
69
69
  @logger = Logger.new(File.join(Rails.root, 'log/service.log'))
70
70
  @logger.level = Rails.env.production? ? Logger::WARN : Logger::DEBUG
71
71
  else
72
- @logger = Logger.new(STDERR)
73
- @logger.level = Logger::WARN
74
- end
72
+ @logger = Logger.new(STDERR)
73
+ @logger.level = Logger::WARN
74
+ end
75
75
  end
76
76
  @logger
77
77
  end
@@ -83,9 +83,9 @@ module Tochtli
83
83
  end
84
84
 
85
85
  def start(queue_name=nil, routing_keys=nil, initial_env={})
86
- run_hook :before_start, queue_name, initial_env
86
+ run_hook :before_start, queue_name, initial_env
87
87
  self.dispatcher.start(queue_name || self.queue_name, routing_keys || self.routing_keys, initial_env)
88
- run_hook :after_start, queue_name, initial_env
88
+ run_hook :after_start, queue_name, initial_env
89
89
  end
90
90
 
91
91
  def set_up?
@@ -97,24 +97,30 @@ module Tochtli
97
97
  end
98
98
 
99
99
  def stop(options={})
100
- if started?
101
- queues = self.dispatcher.queues
102
- run_hook :before_stop, queues
100
+ if started?
101
+ queues = self.dispatcher.queues
102
+ run_hook :before_stop, queues
103
+ end
104
+
105
+ if self.dispatcher
106
+ self.dispatcher.shutdown(options)
107
+ self.dispatcher = nil
103
108
 
104
- self.dispatcher.shutdown(options)
105
- self.dispatcher = nil
109
+ run_hook :after_stop, queues
106
110
 
107
- run_hook :after_stop, queues
108
- end
111
+ true
112
+ else
113
+ false
114
+ end
109
115
  end
110
116
 
111
117
  def restart(options={})
112
- if started?
113
- queues = self.dispatcher.queues
114
- run_hook :before_restart, queues
115
- self.dispatcher.restart options
116
- run_hook :after_restart, queues
117
- end
118
+ if started?
119
+ queues = self.dispatcher.queues
120
+ run_hook :before_restart, queues
121
+ self.dispatcher.restart options
122
+ run_hook :after_restart, queues
123
+ end
118
124
  end
119
125
 
120
126
  def find_message_route(routing_key)
@@ -181,13 +187,13 @@ module Tochtli
181
187
  end
182
188
 
183
189
  def rabbit_connection
184
- self.class.dispatcher.rabbit_connection if self.class.set_up?
190
+ self.class.dispatcher.rabbit_connection if self.class.set_up?
185
191
  end
186
192
 
187
193
  class MessageRoute < Struct.new(:message_class, :action, :routing_key, :pattern)
188
- def initialize(message_class, action, routing_key)
189
- super message_class, action, routing_key, KeyPattern.new(routing_key)
190
- end
194
+ def initialize(message_class, action, routing_key)
195
+ super message_class, action, routing_key, KeyPattern.new(routing_key)
196
+ end
191
197
  end
192
198
 
193
199
  class Dispatcher
@@ -209,13 +215,13 @@ module Tochtli
209
215
  end
210
216
 
211
217
  def restart(options={})
212
- queues = @queues.dup
218
+ queues = @queues.dup
213
219
 
214
- shutdown options
220
+ shutdown options
215
221
 
216
- queues.each do |queue_name, queue_opts|
217
- start queue_name, queue_opts[:initial_env]
218
- end
222
+ queues.each do |queue_name, queue_opts|
223
+ start queue_name, queue_opts[:initial_env]
224
+ end
219
225
  end
220
226
 
221
227
  def process_message(delivery_info, properties, payload, initial_env)
@@ -266,15 +272,15 @@ module Tochtli
266
272
  rescue Bunny::ConnectionClosedError
267
273
  # ignore closed connection error
268
274
  ensure
269
- @queues = {}
275
+ @queues = {}
270
276
  end
271
277
 
272
278
  def started?(queue_name=nil)
273
- if queue_name
274
- @queues.has_key?(queue_name)
275
- else
276
- !@queues.empty?
277
- end
279
+ if queue_name
280
+ @queues.has_key?(queue_name)
281
+ else
282
+ !@queues.empty?
283
+ end
278
284
  end
279
285
 
280
286
  def queues
@@ -326,35 +332,35 @@ module Tochtli
326
332
  end
327
333
 
328
334
  class KeyPattern
329
- ASTERIX_EXP = '[a-zA-Z0-9]+'
330
- HASH_EXP = '[a-zA-Z0-9\.]*'
331
-
332
- def initialize(pattern)
333
- @str = pattern
334
- @simple = !pattern.include?('*') && !pattern.include?('#')
335
- if @simple
336
- @pattern = pattern
337
- else
338
- @pattern = Regexp.new('^' + pattern.gsub('.', '\\.').
339
- gsub('*', ASTERIX_EXP).gsub(/(\\\.)?#(\\\.)?/, HASH_EXP) + '$')
340
- end
341
- end
342
-
343
- def =~(key)
344
- if @simple
345
- @pattern == key
346
- else
347
- @pattern =~ key
348
- end
349
- end
350
-
351
- def !~(key)
352
- !(self =~ key)
353
- end
354
-
355
- def to_s
356
- @str
357
- end
358
- end
335
+ ASTERIX_EXP = '[a-zA-Z0-9]+'
336
+ HASH_EXP = '[a-zA-Z0-9\.]*'
337
+
338
+ def initialize(pattern)
339
+ @str = pattern
340
+ @simple = !pattern.include?('*') && !pattern.include?('#')
341
+ if @simple
342
+ @pattern = pattern
343
+ else
344
+ @pattern = Regexp.new('^' + pattern.gsub('.', '\\.').
345
+ gsub('*', ASTERIX_EXP).gsub(/(\\\.)?#(\\\.)?/, HASH_EXP) + '$')
346
+ end
347
+ end
348
+
349
+ def =~(key)
350
+ if @simple
351
+ @pattern == key
352
+ else
353
+ @pattern =~ key
354
+ end
355
+ end
356
+
357
+ def !~(key)
358
+ !(self =~ key)
359
+ end
360
+
361
+ def to_s
362
+ @str
363
+ end
364
+ end
359
365
  end
360
366
  end
@@ -26,13 +26,13 @@ module Tochtli
26
26
  end
27
27
 
28
28
  def start(*controllers)
29
- options = controllers.extract_options!
30
- setup_options = options.except!(:logger, :cache, :connection)
31
- queue_name = options.delete(:queue_name)
32
- routing_keys = options.delete(:routing_keys)
33
- initial_env = options.delete(:env) || {}
29
+ options = controllers.extract_options!
30
+ setup_options = options.except!(:logger, :cache, :connection)
31
+ queue_name = options.delete(:queue_name)
32
+ routing_keys = options.delete(:routing_keys)
33
+ initial_env = options.delete(:env) || {}
34
34
 
35
- setup(setup_options) unless set_up?
35
+ setup(setup_options) unless set_up?
36
36
 
37
37
  if controllers.empty? || controllers.include?(:all)
38
38
  controllers = @controller_classes
@@ -41,34 +41,33 @@ module Tochtli
41
41
  controllers.each do |controller_class|
42
42
  raise ArgumentError, "Controller expected, got: #{controller_class.inspect}" unless controller_class.is_a?(Class) && controller_class < Tochtli::BaseController
43
43
  unless controller_class.started?(queue_name)
44
- @logger.info "Starting #{controller_class}..." if @logger
45
44
  controller_class.setup(@rabbit_connection, @cache, @logger) unless controller_class.set_up?
46
45
  controller_class.start queue_name, routing_keys, initial_env
46
+ @logger.info "[#{Time.now} AMQP] Started #{controller_class}" if @logger
47
47
  end
48
48
  end
49
49
  end
50
50
 
51
51
  def stop
52
52
  @controller_classes.each do |controller_class|
53
- if controller_class.started?
54
- @logger.info "Stopping #{controller_class}..." if @logger
55
- controller_class.stop
53
+ if controller_class.stop
54
+ @logger.info "[#{Time.now} AMQP] Stopped #{controller_class}" if @logger
56
55
  end
57
56
  end
58
57
  @rabbit_connection = nil
59
58
  end
60
59
 
61
60
  def restart(options={})
62
- options[:rabbit_connection] ||= @rabbit_connection
63
- options[:logger] ||= @logger
64
- options[:cache] ||= @cache
61
+ options[:rabbit_connection] ||= @rabbit_connection
62
+ options[:logger] ||= @logger
63
+ options[:cache] ||= @cache
65
64
 
66
- setup options
67
- restart_active_controllers
65
+ setup options
66
+ restart_active_controllers
68
67
  end
69
68
 
70
69
  def set_up?
71
- !@rabbit_connection.nil?
70
+ !@rabbit_connection.nil?
72
71
  end
73
72
 
74
73
  def running?
@@ -78,17 +77,17 @@ module Tochtli
78
77
  protected
79
78
 
80
79
  def restart_active_controllers
81
- @controller_classes.each do |controller_class|
82
- if controller_class.started?
83
- @logger.info "Restarting #{controller_class}..." if @logger
84
- controller_class.restart
85
- end
86
- end
80
+ @controller_classes.each do |controller_class|
81
+ if controller_class.started?
82
+ @logger.info "Restarting #{controller_class}..." if @logger
83
+ controller_class.restart
84
+ end
85
+ end
87
86
  end
88
87
 
89
88
  class << self
90
89
  def method_missing(method, *args)
91
- if instance.respond_to?(method)
90
+ if instance.respond_to?(method)
92
91
  instance.send(method, *args)
93
92
  else
94
93
  super
@@ -88,11 +88,11 @@ module Tochtli
88
88
  end
89
89
 
90
90
  def routing_key
91
- if self.class.routing_key.is_a?(Proc)
92
- self.instance_eval(&self.class.routing_key)
93
- else
91
+ if self.class.routing_key.is_a?(Proc)
92
+ self.instance_eval(&self.class.routing_key)
93
+ else
94
94
  self.class.routing_key
95
- end
95
+ end
96
96
  end
97
97
 
98
98
  def to_hash
@@ -16,6 +16,7 @@ module Tochtli
16
16
  @client = Tochtli::RabbitClient.new(nil, @logger)
17
17
  @connection = @client.rabbit_connection
18
18
  @controller_manager = Tochtli::ControllerManager.instance
19
+ @controller_manager.stop # restart all controllers - some can be started with functional tests on test connections
19
20
  @controller_manager.setup(connection: @connection, logger: @logger)
20
21
  @controller_manager.start(:all)
21
22
 
@@ -5,7 +5,7 @@ SEVERITIES = [:fatal] + [:error]*3 + [:warn]*5 + [:info]*12 + [:debug]*20
5
5
  log = Logger.new('sample.log')
6
6
 
7
7
  10000.times do
8
- severity = SEVERITIES.sample
9
- log.send severity, "Sample #{severity}"
8
+ severity = SEVERITIES.sample
9
+ log.send severity, "Sample #{severity}"
10
10
  end
11
11
 
@@ -11,7 +11,7 @@ class ControllerFunctionalTest < Minitest::Test
11
11
  end
12
12
 
13
13
  class CustomTopicMessage < Tochtli::Message
14
- route_to { "fn.test.#{key}.#{action}" }
14
+ route_to { "fn.test.#{key}.#{action}" }
15
15
 
16
16
  attribute :resource, String
17
17
 
@@ -40,7 +40,7 @@ class ControllerFunctionalTest < Minitest::Test
40
40
  off 'fn.test.off.accept'
41
41
 
42
42
  on CustomTopicMessage, routing_key: 'fn.test.*.reject' do
43
- reply TestCustomReply.new(:message => "#{message.resource} rejected")
43
+ reply TestCustomReply.new(:message => "#{message.resource} rejected")
44
44
  end
45
45
 
46
46
  def echo
@@ -56,20 +56,20 @@ class ControllerManagerTest < Minitest::Test
56
56
  Tochtli::ControllerManager.start(FirstController, connection: @connection, logger: @logger)
57
57
  end
58
58
 
59
- def test_multiple_queues
60
- Tochtli::ControllerManager.setup(connection: @connection, logger: @logger)
61
- Tochtli::ControllerManager.start(FirstController, queue_name: 'first_queue')
62
- Tochtli::ControllerManager.start(FirstController, queue_name: 'second_queue')
59
+ def test_multiple_queues
60
+ Tochtli::ControllerManager.setup(connection: @connection, logger: @logger)
61
+ Tochtli::ControllerManager.start(FirstController, queue_name: 'first_queue')
62
+ Tochtli::ControllerManager.start(FirstController, queue_name: 'second_queue')
63
63
 
64
- assert_equal ["first_queue", "second_queue"], FirstController.dispatcher.queues.map(&:name).sort
65
- end
64
+ assert_equal ["first_queue", "second_queue"], FirstController.dispatcher.queues.map(&:name).sort
65
+ end
66
66
 
67
- def test_restart_multiple_queues
68
- Tochtli::ControllerManager.setup(connection: @connection, logger: @logger)
69
- Tochtli::ControllerManager.start(FirstController, queue_name: 'first_queue')
70
- Tochtli::ControllerManager.start(FirstController, queue_name: 'second_queue')
71
- Tochtli::ControllerManager.restart
67
+ def test_restart_multiple_queues
68
+ Tochtli::ControllerManager.setup(connection: @connection, logger: @logger)
69
+ Tochtli::ControllerManager.start(FirstController, queue_name: 'first_queue')
70
+ Tochtli::ControllerManager.start(FirstController, queue_name: 'second_queue')
71
+ Tochtli::ControllerManager.restart
72
72
 
73
- assert_equal ["first_queue", "second_queue"], FirstController.dispatcher.queues.map(&:name).sort
74
- end
73
+ assert_equal ["first_queue", "second_queue"], FirstController.dispatcher.queues.map(&:name).sort
74
+ end
75
75
  end
@@ -2,99 +2,99 @@ require_relative 'test_helper'
2
2
  require 'benchmark'
3
3
 
4
4
  class MessageTest < Minitest::Test
5
- KeyPattern = Tochtli::BaseController::KeyPattern
5
+ KeyPattern = Tochtli::BaseController::KeyPattern
6
6
 
7
- def test_simple_pattern
8
- pattern = KeyPattern.new('a.b.c')
7
+ def test_simple_pattern
8
+ pattern = KeyPattern.new('a.b.c')
9
9
 
10
- assert_matches pattern, 'a.b.c'
11
- refute_matches pattern, 'a.b.c.d'
12
- refute_matches pattern, 'b.c.d'
13
- end
10
+ assert_matches pattern, 'a.b.c'
11
+ refute_matches pattern, 'a.b.c.d'
12
+ refute_matches pattern, 'b.c.d'
13
+ end
14
14
 
15
- def test_asterix_at_start
16
- pattern = KeyPattern.new('*.b.c')
15
+ def test_asterix_at_start
16
+ pattern = KeyPattern.new('*.b.c')
17
17
 
18
- assert_matches pattern, 'a.b.c'
19
- assert_matches pattern, 'b.b.c'
20
- refute_matches pattern, 'a.b.c.d'
21
- end
18
+ assert_matches pattern, 'a.b.c'
19
+ assert_matches pattern, 'b.b.c'
20
+ refute_matches pattern, 'a.b.c.d'
21
+ end
22
22
 
23
- def test_asterix_in_the_middle
24
- pattern = KeyPattern.new('a.*.b.c')
23
+ def test_asterix_in_the_middle
24
+ pattern = KeyPattern.new('a.*.b.c')
25
25
 
26
- assert_matches pattern, 'a.a.b.c'
27
- assert_matches pattern, 'a.d.b.c'
28
- refute_matches pattern, 'a.b.c.d'
29
- end
26
+ assert_matches pattern, 'a.a.b.c'
27
+ assert_matches pattern, 'a.d.b.c'
28
+ refute_matches pattern, 'a.b.c.d'
29
+ end
30
30
 
31
- def test_asterix_at_the_end
32
- pattern = KeyPattern.new('a.b.c.*')
31
+ def test_asterix_at_the_end
32
+ pattern = KeyPattern.new('a.b.c.*')
33
33
 
34
- assert_matches pattern, 'a.b.c.d'
35
- assert_matches pattern, 'a.b.c.a'
36
- refute_matches pattern, 'a.b.c'
37
- refute_matches pattern, 'a.b.c.d.e'
38
- end
34
+ assert_matches pattern, 'a.b.c.d'
35
+ assert_matches pattern, 'a.b.c.a'
36
+ refute_matches pattern, 'a.b.c'
37
+ refute_matches pattern, 'a.b.c.d.e'
38
+ end
39
39
 
40
- def test_hash
41
- pattern = KeyPattern.new('#')
40
+ def test_hash
41
+ pattern = KeyPattern.new('#')
42
42
 
43
- assert_matches pattern, ''
44
- assert_matches pattern, 'a.b.c'
45
- assert_matches pattern, 'a.b.b.c'
46
- end
43
+ assert_matches pattern, ''
44
+ assert_matches pattern, 'a.b.c'
45
+ assert_matches pattern, 'a.b.b.c'
46
+ end
47
47
 
48
- def test_hash_at_start
49
- pattern = KeyPattern.new('#.b.c')
48
+ def test_hash_at_start
49
+ pattern = KeyPattern.new('#.b.c')
50
50
 
51
- assert_matches pattern, 'b.c'
52
- assert_matches pattern, 'a.b.c'
53
- assert_matches pattern, 'a.b.b.c'
54
- refute_matches pattern, 'a.b.c.d'
55
- end
51
+ assert_matches pattern, 'b.c'
52
+ assert_matches pattern, 'a.b.c'
53
+ assert_matches pattern, 'a.b.b.c'
54
+ refute_matches pattern, 'a.b.c.d'
55
+ end
56
56
 
57
- def test_hash_in_the_middle
58
- pattern = KeyPattern.new('a.#.c')
57
+ def test_hash_in_the_middle
58
+ pattern = KeyPattern.new('a.#.c')
59
59
 
60
- assert_matches pattern, 'a.a.b.c'
61
- assert_matches pattern, 'a.d.b.c'
62
- refute_matches pattern, 'a.b.c.d'
63
- end
60
+ assert_matches pattern, 'a.a.b.c'
61
+ assert_matches pattern, 'a.d.b.c'
62
+ refute_matches pattern, 'a.b.c.d'
63
+ end
64
64
 
65
- def test_hash_at_the_end
66
- pattern = KeyPattern.new('a.b.#')
65
+ def test_hash_at_the_end
66
+ pattern = KeyPattern.new('a.b.#')
67
67
 
68
- assert_matches pattern, 'a.b.c.d'
69
- assert_matches pattern, 'a.b.c'
70
- assert_matches pattern, 'a.b.c.d.e'
71
- end
68
+ assert_matches pattern, 'a.b.c.d'
69
+ assert_matches pattern, 'a.b.c'
70
+ assert_matches pattern, 'a.b.c.d.e'
71
+ end
72
72
 
73
- def test_complex
74
- pattern = KeyPattern.new('*.*.a.b.#.c.#')
73
+ def test_complex
74
+ pattern = KeyPattern.new('*.*.a.b.#.c.#')
75
75
 
76
- assert_matches pattern, '1.2.a.b.c.d'
77
- assert_matches pattern, '1.2.a.b.3.4.c.d'
78
- assert_matches pattern, '1.2.a.b.c'
79
- refute_matches pattern, 'a.b.c.d.e'
80
- end
76
+ assert_matches pattern, '1.2.a.b.c.d'
77
+ assert_matches pattern, '1.2.a.b.3.4.c.d'
78
+ assert_matches pattern, '1.2.a.b.c'
79
+ refute_matches pattern, 'a.b.c.d.e'
80
+ end
81
81
 
82
- def test_performance
83
- pattern = KeyPattern.new('*.*.a.b.#.c.#')
82
+ def test_performance
83
+ pattern = KeyPattern.new('*.*.a.b.#.c.#')
84
84
 
85
- n = 10_000
86
- time = Benchmark.realtime { n.times { pattern =~ '1.2.a.b.3.4.c.d' } }
85
+ n = 10_000
86
+ time = Benchmark.realtime { n.times { pattern =~ '1.2.a.b.3.4.c.d' } }
87
87
 
88
- assert time < 0.1
89
- end
88
+ assert time < 0.1
89
+ end
90
90
 
91
- protected
91
+ protected
92
92
 
93
- def assert_matches(pattern, key)
94
- assert pattern =~ key, "#{key} SHOULD match #{pattern}"
95
- end
93
+ def assert_matches(pattern, key)
94
+ assert pattern =~ key, "#{key} SHOULD match #{pattern}"
95
+ end
96
96
 
97
- def refute_matches(pattern, key)
98
- assert pattern !~ key, "#{key} MUST NOT match #{pattern}"
99
- end
97
+ def refute_matches(pattern, key)
98
+ assert pattern !~ key, "#{key} MUST NOT match #{pattern}"
99
+ end
100
100
  end
@@ -1,151 +1,151 @@
1
- require_relative 'test_helper'
2
- require 'tochtli/test/test_case'
3
-
4
- class RabbitConnectionTest < Minitest::Test
5
- def setup
6
- Tochtli::RabbitConnection.close('test')
7
- end
8
-
9
- def teardown
10
- Tochtli::RabbitConnection.close('test')
11
- end
12
-
13
- class TestMessage < Tochtli::Message
14
- attributes :text
15
- end
16
-
17
- def test_connection_with_default_options
18
- Tochtli::RabbitConnection.open('test') do |connection|
19
- assert_equal "puzzleflow.services", connection.exchange.name
20
- end
21
- end
22
-
23
- def test_connection_with_custom_options
24
- Tochtli::RabbitConnection.open('test', exchange_name: "puzzleflow.tests") do |connection|
25
- assert_equal "puzzleflow.tests", connection.exchange.name
26
- end
27
- end
28
-
29
- def test_multiple_channels_and_exchanges
30
- Tochtli::RabbitConnection.open('test', exchange_name: "puzzleflow.tests") do |connection|
31
- another_thread = Thread.new {}
32
-
33
- current_channel = connection.channel
34
- another_channel = connection.channel(another_thread)
35
-
36
- current_exchange = connection.exchange
37
- another_exchange = connection.exchange(another_thread)
38
-
39
- refute_equal current_channel, another_channel
40
- refute_equal current_exchange, another_exchange
41
- assert_equal "puzzleflow.tests", current_exchange.name
42
- assert_equal "puzzleflow.tests", another_exchange.name
43
- end
44
- end
45
-
46
- def test_queue_creation_and_existance
47
- Tochtli::RabbitConnection.open('test') do |connection|
48
- queue = connection.queue('test-queue', [], auto_delete: true)
49
- refute_nil queue
50
- assert_equal 'test-queue', queue.name
51
- assert connection.queue_exists?('test-queue')
52
- end
53
- end
54
-
55
- def test_reply_queue_recovery
56
- Tochtli::RabbitConnection.open('test',
57
- network_recovery_interval: 0.1,
58
- recover_from_connection_close: true) do |rabbit_connection|
59
- reply_queue = rabbit_connection.reply_queue
60
- original_name = reply_queue.name
61
- timeout = 0.3
62
-
63
- message = TestMessage.new(text: "Response")
64
- reply = TestMessage.new(text: "Reply")
65
- handler = Tochtli::Test::TestMessageHandler.new
66
- reply_queue.register_message_handler message, handler, timeout
67
-
68
- rabbit_connection.publish reply_queue.name, reply, correlation_id: message.id, timeout: timeout
69
- sleep timeout
70
-
71
- refute_nil handler.reply
72
-
73
- # simulate network failure
74
- rabbit_connection.connection.handle_network_failure(RuntimeError.new('fake connection error'))
75
- sleep 0.1 until rabbit_connection.open? # wait for recovery
76
- refute_equal original_name, reply_queue.name, "Recovered queue should have re-generated name"
77
-
78
- message = TestMessage.new(text: "Response")
79
- reply = TestMessage.new(text: "Reply")
80
- handler = Tochtli::Test::TestMessageHandler.new
81
- reply_queue.register_message_handler message, handler, timeout
82
-
83
- rabbit_connection.publish reply_queue.name, reply, correlation_id: message.id, timeout: timeout
84
- sleep timeout
85
-
86
- refute_nil handler.reply
87
- end
88
- end
89
-
90
- def test_multithreaded_consumer_performance
91
- work_pool_size = 10
92
- Tochtli::RabbitConnection.open('test',
93
- exchange_name: "puzzleflow.tests",
94
- work_pool_size: work_pool_size) do |connection|
95
- mutex = Mutex.new
96
- cv = ConditionVariable.new
97
- thread_count = 5
98
- message_count = 100
99
- expected_message_count = message_count*thread_count
100
-
101
- consumed = 0
102
- consumed_mutex = Mutex.new
103
- consumer_threads = Set.new
104
- consumer = Proc.new do |delivery_info, metadata, payload|
105
- consumed_mutex.synchronize { consumed += 1 }
106
- consumer_threads << Thread.current
107
- connection.publish metadata.reply_to, TestMessage.new(text: "Response to #{payload}")
108
- end
109
-
110
- queue = connection.channel.queue('', auto_delete: true)
111
- queue.bind(connection.exchange, routing_key: queue.name)
112
- queue.subscribe(block: false, &consumer)
113
-
114
- replies = 0
115
- reply_consumer = Proc.new do |delivery_info, metadata, payload|
116
- replies += 1
117
- mutex.synchronize { cv.signal } if replies == expected_message_count
118
- end
119
-
120
- reply_queue = connection.channel.queue('', auto_delete: true)
121
- reply_queue.bind(connection.exchange, routing_key: reply_queue.name)
122
- reply_queue.subscribe(block: false, &reply_consumer)
123
-
124
- start_t = Time.now
125
-
126
- threads = (1..thread_count).collect do
127
- t = Thread.new do
128
- message_count.times do |i|
129
- connection.publish queue.name, TestMessage.new(text: "Message #{i}"),
130
- reply_to: reply_queue.name
131
- end
132
- end
133
- t.abort_on_exception = true
134
- t
135
- end
136
-
137
- threads.each(&:join)
138
-
139
- mutex.synchronize { cv.wait(mutex, 5.0) }
140
-
141
- end_t = Time.now
142
- time = end_t - start_t
143
-
144
- assert_equal expected_message_count, consumed
145
- assert_equal expected_message_count, replies
146
- assert_equal work_pool_size, consumer_threads.size
147
-
148
- puts "Published: #{expected_message_count} in #{time} (#{expected_message_count/time}req/s)"
149
- end
150
- end
151
- end
1
+ require_relative 'test_helper'
2
+ require 'tochtli/test/test_case'
3
+
4
+ class RabbitConnectionTest < Minitest::Test
5
+ def setup
6
+ Tochtli::RabbitConnection.close('test')
7
+ end
8
+
9
+ def teardown
10
+ Tochtli::RabbitConnection.close('test')
11
+ end
12
+
13
+ class TestMessage < Tochtli::Message
14
+ attributes :text
15
+ end
16
+
17
+ def test_connection_with_default_options
18
+ Tochtli::RabbitConnection.open('test') do |connection|
19
+ assert_equal "puzzleflow.services", connection.exchange.name
20
+ end
21
+ end
22
+
23
+ def test_connection_with_custom_options
24
+ Tochtli::RabbitConnection.open('test', exchange_name: "puzzleflow.tests") do |connection|
25
+ assert_equal "puzzleflow.tests", connection.exchange.name
26
+ end
27
+ end
28
+
29
+ def test_multiple_channels_and_exchanges
30
+ Tochtli::RabbitConnection.open('test', exchange_name: "puzzleflow.tests") do |connection|
31
+ another_thread = Thread.new {}
32
+
33
+ current_channel = connection.channel
34
+ another_channel = connection.channel(another_thread)
35
+
36
+ current_exchange = connection.exchange
37
+ another_exchange = connection.exchange(another_thread)
38
+
39
+ refute_equal current_channel, another_channel
40
+ refute_equal current_exchange, another_exchange
41
+ assert_equal "puzzleflow.tests", current_exchange.name
42
+ assert_equal "puzzleflow.tests", another_exchange.name
43
+ end
44
+ end
45
+
46
+ def test_queue_creation_and_existance
47
+ Tochtli::RabbitConnection.open('test') do |connection|
48
+ queue = connection.queue('test-queue', [], auto_delete: true)
49
+ refute_nil queue
50
+ assert_equal 'test-queue', queue.name
51
+ assert connection.queue_exists?('test-queue')
52
+ end
53
+ end
54
+
55
+ def test_reply_queue_recovery
56
+ Tochtli::RabbitConnection.open('test',
57
+ network_recovery_interval: 0.1,
58
+ recover_from_connection_close: true) do |rabbit_connection|
59
+ reply_queue = rabbit_connection.reply_queue
60
+ original_name = reply_queue.name
61
+ timeout = 0.3
62
+
63
+ message = TestMessage.new(text: "Response")
64
+ reply = TestMessage.new(text: "Reply")
65
+ handler = Tochtli::Test::TestMessageHandler.new
66
+ reply_queue.register_message_handler message, handler, timeout
67
+
68
+ rabbit_connection.publish reply_queue.name, reply, correlation_id: message.id, timeout: timeout
69
+ sleep timeout
70
+
71
+ refute_nil handler.reply
72
+
73
+ # simulate network failure
74
+ rabbit_connection.connection.handle_network_failure(RuntimeError.new('fake connection error'))
75
+ sleep 0.1 until rabbit_connection.open? # wait for recovery
76
+ refute_equal original_name, reply_queue.name, "Recovered queue should have re-generated name"
77
+
78
+ message = TestMessage.new(text: "Response")
79
+ reply = TestMessage.new(text: "Reply")
80
+ handler = Tochtli::Test::TestMessageHandler.new
81
+ reply_queue.register_message_handler message, handler, timeout
82
+
83
+ rabbit_connection.publish reply_queue.name, reply, correlation_id: message.id, timeout: timeout
84
+ sleep timeout
85
+
86
+ refute_nil handler.reply
87
+ end
88
+ end
89
+
90
+ def test_multithreaded_consumer_performance
91
+ work_pool_size = 10
92
+ Tochtli::RabbitConnection.open('test',
93
+ exchange_name: "puzzleflow.tests",
94
+ work_pool_size: work_pool_size) do |connection|
95
+ mutex = Mutex.new
96
+ cv = ConditionVariable.new
97
+ thread_count = 5
98
+ message_count = 100
99
+ expected_message_count = message_count*thread_count
100
+
101
+ consumed = 0
102
+ consumed_mutex = Mutex.new
103
+ consumer_threads = Set.new
104
+ consumer = Proc.new do |delivery_info, metadata, payload|
105
+ consumed_mutex.synchronize { consumed += 1 }
106
+ consumer_threads << Thread.current
107
+ connection.publish metadata.reply_to, TestMessage.new(text: "Response to #{payload}")
108
+ end
109
+
110
+ queue = connection.channel.queue('', auto_delete: true)
111
+ queue.bind(connection.exchange, routing_key: queue.name)
112
+ queue.subscribe(block: false, &consumer)
113
+
114
+ replies = 0
115
+ reply_consumer = Proc.new do |delivery_info, metadata, payload|
116
+ replies += 1
117
+ mutex.synchronize { cv.signal } if replies == expected_message_count
118
+ end
119
+
120
+ reply_queue = connection.channel.queue('', auto_delete: true)
121
+ reply_queue.bind(connection.exchange, routing_key: reply_queue.name)
122
+ reply_queue.subscribe(block: false, &reply_consumer)
123
+
124
+ start_t = Time.now
125
+
126
+ threads = (1..thread_count).collect do
127
+ t = Thread.new do
128
+ message_count.times do |i|
129
+ connection.publish queue.name, TestMessage.new(text: "Message #{i}"),
130
+ reply_to: reply_queue.name
131
+ end
132
+ end
133
+ t.abort_on_exception = true
134
+ t
135
+ end
136
+
137
+ threads.each(&:join)
138
+
139
+ mutex.synchronize { cv.wait(mutex, 5.0) }
140
+
141
+ end_t = Time.now
142
+ time = end_t - start_t
143
+
144
+ assert_equal expected_message_count, consumed
145
+ assert_equal expected_message_count, replies
146
+ assert_equal work_pool_size, consumer_threads.size
147
+
148
+ puts "Published: #{expected_message_count} in #{time} (#{expected_message_count/time}req/s)"
149
+ end
150
+ end
151
+ end
@@ -1,8 +1,8 @@
1
1
  require_relative 'test_helper'
2
2
 
3
3
  class VersionTest < Minitest::Test
4
- def test_version_match
5
- spec = Gem::Specification::load(File.expand_path('../../tochtli.gemspec', __FILE__))
6
- assert_equal Tochtli::VERSION, spec.version.to_s, "Gem version mismatch. Run: 'rake gemspec'"
7
- end
4
+ def test_version_match
5
+ spec = Gem::Specification::load(File.expand_path('../../tochtli.gemspec', __FILE__))
6
+ assert_equal Tochtli::VERSION, spec.version.to_s, "Gem version mismatch. Run: 'rake gemspec'"
7
+ end
8
8
  end
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: tochtli 0.5.0 ruby lib
5
+ # stub: tochtli 0.5.1 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "tochtli"
9
- s.version = "0.5.0"
9
+ s.version = "0.5.1"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Rafal Bigaj"]
14
- s.date = "2015-08-19"
14
+ s.date = "2015-08-20"
15
15
  s.description = "Lightweight framework for service oriented applications based on bunny (RabbitMQ)"
16
16
  s.email = "rafal.bigaj@puzzleflow.com"
17
17
  s.extra_rdoc_files = [
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tochtli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rafal Bigaj
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-19 00:00:00.000000000 Z
11
+ date: 2015-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny