baton 0.4.4 → 0.4.5

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.
@@ -5,20 +5,28 @@ module Baton
5
5
  class Channel
6
6
  include Baton::Logging
7
7
 
8
- attr_accessor :channel, :exchange_in, :exchange_out, :connection
8
+ attr_accessor :channel, :exchange_in, :exchange_out, :connection, :connection_options, :amqp_hosts
9
9
 
10
10
  # Public: Initialize a Channel. It creates an AMQP connection, a channel,
11
11
  # an input and an output exchange and finally attaches the handle_channel_exception
12
12
  # callback to the on_error event on the channel.
13
13
  def initialize
14
- @connection = AMQP.connect(Baton.configuration.connection_opts)
14
+
15
+ @connection_options = Baton.configuration.connection_opts
16
+ @amqp_hosts = Baton.configuration.amqp_host_list
17
+
18
+ logger.info "Connecting to AMQP host: #{@connection_options[:host]}"
19
+
20
+ @connection = AMQP.connect(@connection_options)
15
21
  @channel = AMQP::Channel.new(@connection)
22
+ @channel.auto_recovery = true
16
23
  @exchange_in = channel.direct(Baton.configuration.exchange)
17
24
  @exchange_out = channel.direct(Baton.configuration.exchange_out)
18
25
  @connection.on_tcp_connection_loss(&method(:handle_tcp_failure))
19
26
  @channel.on_error(&method(:handle_channel_exception))
20
27
  end
21
28
 
29
+
22
30
  # Public: creates a consumer manager with a consumer attached and starts
23
31
  # listening to messages.
24
32
  #
@@ -45,15 +53,45 @@ module Baton
45
53
  logger.error "Channel-level exception: code = #{channel_close.reply_code}, message = #{channel_close.reply_text}"
46
54
  end
47
55
 
56
+ # Public: Provides a new AMQP hostname
57
+ #
58
+ # amqp_hosts - An array of hostnames for your AMQP servers
59
+ #
60
+ # Returns a string of an AMQP hostname.
61
+ #
62
+ def get_new_amqp_host(amqp_hosts)
63
+ amqp_hosts[Kernel.rand(amqp_hosts.size)]
64
+ end
65
+
48
66
  # Public: Callback to handle TCP connection loss
49
67
  #
50
68
  # connection - An AMQP Connection
51
- # settings -
69
+ # settings - Current AMQP settings (see amq-client/lib/amq/client/settings.rb and lib/amq/client/async/adapter.rb)
52
70
  #
53
71
  # Returns nothing.
54
72
  #
55
73
  def handle_tcp_failure(connection, settings)
56
- connection.reconnect(false, 10)
74
+
75
+ logger.info("Connection to AMQP lost. Finding new host..")
76
+
77
+ if @amqp_hosts.size == 1
78
+ logger.info("Only a single host.. reconnecting")
79
+ connection.reconnect(false, 10)
80
+ return
81
+ end
82
+
83
+ current_host = settings[:host]
84
+ new_host = get_new_amqp_host(@amqp_hosts)
85
+
86
+ while new_host == current_host
87
+ new_host = get_new_amqp_host(@amqp_hosts)
88
+ end
89
+
90
+ settings[:host] = new_host
91
+
92
+ logger.info ("Reconnecting to AMPQ host: #{new_host}")
93
+
94
+ connection.reconnect_to(settings)
57
95
  end
58
96
  end
59
97
  end
@@ -5,7 +5,7 @@ module Baton
5
5
  class Configuration
6
6
  include Baton::Logging
7
7
 
8
- attr_accessor :config, :host, :vhost, :user, :password
8
+ attr_accessor :config, :host, :vhost, :user, :password, :amqp_host_list
9
9
 
10
10
  def initialize
11
11
  @config = {}
@@ -40,22 +40,42 @@ module Baton
40
40
  logger.error "Could not find a baton configuration file at #{path}"
41
41
  end
42
42
 
43
- # Public: Setup RabbitMQ's options from a config file.
43
+ # Public: Setup RabbitMQ's options from a config file. You have the option of
44
+ # passing in a comma seperated string of RabbitMQ servers to connect to. When
45
+ # using a pool of servers one will be randomly picked for the initial connection.
44
46
  #
45
47
  # config_file - A hash representing a config file
46
48
  #
47
49
  # Examples
48
50
  #
49
- # setup_rabbitmq_opts({
51
+ # # Single RabbitMQ server
52
+ # config = {
50
53
  # "RABBIT_HOST" => "localhost",
51
54
  # "RABBIT_VHOST" => "baton",
52
55
  # "RABBIT_USER" => "baton",
53
56
  # "RABBIT_PASS" => "password"
54
- # })
57
+ # }
58
+ #
59
+ # # Use a pool of RabbitMQ servers
60
+ # config = {
61
+ # "RABBIT_HOST" => "host1,host2,host3",
62
+ # "RABBIT_VHOST" => "baton",
63
+ # "RABBIT_USER" => "baton",
64
+ # "RABBIT_PASS" => "password"
65
+ # }
66
+ #
67
+ # setup_rabbitmq_opts
55
68
  #
56
69
  # Returns nothing.
57
70
  def setup_rabbitmq_opts
58
- self.host = config.fetch("RABBIT_HOST") {"localhost"}
71
+
72
+ rabbit_hosts = config.fetch("RABBIT_HOST") {"localhost"}
73
+ rabbit_hosts = rabbit_hosts.split(',')
74
+
75
+ # Pick a random host to connect to
76
+ self.host = rabbit_hosts[Kernel.rand(rabbit_hosts.size)]
77
+ self.amqp_host_list = rabbit_hosts
78
+
59
79
  self.vhost = config["RABBIT_VHOST"]
60
80
  self.user = config["RABBIT_USER"]
61
81
  self.password = config["RABBIT_PASS"]
@@ -4,6 +4,7 @@ require "baton/<%= config[:name] %>/<%= config[:name] %>-monitor"
4
4
 
5
5
  Baton.configure do |c|
6
6
  c.config_path = "<%= File.join(Dir.pwd, config[:name], 'config', config[:name]) %>.cfg"
7
+ c.exchange = "<%= config[:name] %>_monitor_in"
7
8
  c.exchange_out = "<%= config[:name] %>_out"
8
9
  end
9
10
 
@@ -2,6 +2,7 @@ require "baton"
2
2
  require "amqp"
3
3
  require "json"
4
4
  require "eventmachine"
5
+ require "baton/channel"
5
6
 
6
7
  module Baton
7
8
  class <%= config[:constant_array].last %>Monitor
@@ -15,11 +16,10 @@ module Baton
15
16
  def run
16
17
  logger.info "Starting <%= config[:name] %> monitor v#{Baton::VERSION}"
17
18
  EM.run do
18
- connection = AMQP.connect(Baton.configuration.connection_opts)
19
19
 
20
- channel = AMQP::Channel.new(connection)
21
- queue = channel.queue("<%= config[:name] %>-monitor")
22
- exchange_out = channel.direct(Baton.configuration.exchange_out)
20
+ baton_channel = Baton::Channel.new
21
+ queue = baton_channel.channel.queue("<%= config[:name] %>-monitor")
22
+ exchange_out = baton_channel.channel.direct(Baton.configuration.exchange_out)
23
23
 
24
24
  queue.bind(exchange_out).subscribe do |payload|
25
25
  logger.info "Message read: #{payload}"
@@ -1,3 +1,3 @@
1
1
  module Baton
2
- VERSION = "0.4.4"
2
+ VERSION = "0.4.5"
3
3
  end
@@ -51,4 +51,21 @@ describe Baton::Configuration do
51
51
  end
52
52
  end
53
53
  end
54
- end
54
+
55
+ describe "multiple amqp hosts" do
56
+
57
+ before do
58
+ Kernel.stub!(:rand).and_return(1)
59
+ subject.config_path = "#{File.dirname(__FILE__)}/../fixtures/config-multi.cfg"
60
+ end
61
+
62
+ it "will set the host" do
63
+ subject.host.should eq("moreconfig.com")
64
+ end
65
+
66
+ it "will have an amqp host list" do
67
+ subject.amqp_host_list.should eq(["fromconfig.com", "moreconfig.com", "thirdconfig.com"])
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,4 @@
1
+ RABBIT_HOST: fromconfig.com,moreconfig.com,thirdconfig.com
2
+ RABBIT_VHOST: fromconfig
3
+ RABBIT_USER: fromconfiguser
4
+ RABBIT_PASS: fromconfigpass
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: baton
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.4.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-04-17 00:00:00.000000000 Z
13
+ date: 2012-04-20 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: amqp
17
- requirement: &70197645261200 !ruby/object:Gem::Requirement
17
+ requirement: &70266370641740 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: 0.8.4
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70197645261200
25
+ version_requirements: *70266370641740
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: eventmachine
28
- requirement: &70197645260580 !ruby/object:Gem::Requirement
28
+ requirement: &70266370640380 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ~>
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: 1.0.0.beta.4
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70197645260580
36
+ version_requirements: *70266370640380
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: em-http-request
39
- requirement: &70197645259780 !ruby/object:Gem::Requirement
39
+ requirement: &70266370639480 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - =
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: 1.0.0
45
45
  type: :runtime
46
46
  prerelease: false
47
- version_requirements: *70197645259780
47
+ version_requirements: *70266370639480
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: bunny
50
- requirement: &70197645259160 !ruby/object:Gem::Requirement
50
+ requirement: &70266370638360 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ~>
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: 0.7.8
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *70197645259160
58
+ version_requirements: *70266370638360
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: ohai
61
- requirement: &70197645258120 !ruby/object:Gem::Requirement
61
+ requirement: &70266370637580 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ~>
@@ -66,10 +66,10 @@ dependencies:
66
66
  version: 0.6.12
67
67
  type: :runtime
68
68
  prerelease: false
69
- version_requirements: *70197645258120
69
+ version_requirements: *70266370637580
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: thor
72
- requirement: &70197645257680 !ruby/object:Gem::Requirement
72
+ requirement: &70266370635720 !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
75
  - - ! '>='
@@ -77,10 +77,10 @@ dependencies:
77
77
  version: '0'
78
78
  type: :runtime
79
79
  prerelease: false
80
- version_requirements: *70197645257680
80
+ version_requirements: *70266370635720
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: rspec
83
- requirement: &70197645256880 !ruby/object:Gem::Requirement
83
+ requirement: &70266370650760 !ruby/object:Gem::Requirement
84
84
  none: false
85
85
  requirements:
86
86
  - - ~>
@@ -88,10 +88,10 @@ dependencies:
88
88
  version: '2.7'
89
89
  type: :development
90
90
  prerelease: false
91
- version_requirements: *70197645256880
91
+ version_requirements: *70266370650760
92
92
  - !ruby/object:Gem::Dependency
93
93
  name: moqueue
94
- requirement: &70197645278680 !ruby/object:Gem::Requirement
94
+ requirement: &70266370648860 !ruby/object:Gem::Requirement
95
95
  none: false
96
96
  requirements:
97
97
  - - ~>
@@ -99,10 +99,10 @@ dependencies:
99
99
  version: 0.1.4
100
100
  type: :development
101
101
  prerelease: false
102
- version_requirements: *70197645278680
102
+ version_requirements: *70266370648860
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: fakefs
105
- requirement: &70197645278220 !ruby/object:Gem::Requirement
105
+ requirement: &70266370647660 !ruby/object:Gem::Requirement
106
106
  none: false
107
107
  requirements:
108
108
  - - ~>
@@ -110,10 +110,10 @@ dependencies:
110
110
  version: 0.4.0
111
111
  type: :development
112
112
  prerelease: false
113
- version_requirements: *70197645278220
113
+ version_requirements: *70266370647660
114
114
  - !ruby/object:Gem::Dependency
115
115
  name: rake
116
- requirement: &70197645277620 !ruby/object:Gem::Requirement
116
+ requirement: &70266370645600 !ruby/object:Gem::Requirement
117
117
  none: false
118
118
  requirements:
119
119
  - - ~>
@@ -121,10 +121,10 @@ dependencies:
121
121
  version: 0.9.2
122
122
  type: :development
123
123
  prerelease: false
124
- version_requirements: *70197645277620
124
+ version_requirements: *70266370645600
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: webmock
127
- requirement: &70197645277080 !ruby/object:Gem::Requirement
127
+ requirement: &70266370644560 !ruby/object:Gem::Requirement
128
128
  none: false
129
129
  requirements:
130
130
  - - ~>
@@ -132,10 +132,10 @@ dependencies:
132
132
  version: 1.7.7
133
133
  type: :development
134
134
  prerelease: false
135
- version_requirements: *70197645277080
135
+ version_requirements: *70266370644560
136
136
  - !ruby/object:Gem::Dependency
137
137
  name: minitar
138
- requirement: &70197645276560 !ruby/object:Gem::Requirement
138
+ requirement: &70266370683360 !ruby/object:Gem::Requirement
139
139
  none: false
140
140
  requirements:
141
141
  - - =
@@ -143,7 +143,7 @@ dependencies:
143
143
  version: 0.5.3
144
144
  type: :development
145
145
  prerelease: false
146
- version_requirements: *70197645276560
146
+ version_requirements: *70266370683360
147
147
  description: Baton
148
148
  email:
149
149
  - johnog@gmail.com
@@ -194,6 +194,7 @@ files:
194
194
  - spec/baton/consumer_manager_spec.rb
195
195
  - spec/baton/consumer_spec.rb
196
196
  - spec/baton/server_spec.rb
197
+ - spec/fixtures/config-multi.cfg
197
198
  - spec/fixtures/config.cfg
198
199
  - spec/fixtures/file
199
200
  - spec/fixtures/file.sum
@@ -214,7 +215,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
214
215
  version: '0'
215
216
  segments:
216
217
  - 0
217
- hash: -4221078928752285961
218
+ hash: 2228522700796728917
218
219
  required_rubygems_version: !ruby/object:Gem::Requirement
219
220
  none: false
220
221
  requirements:
@@ -223,7 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
223
224
  version: '0'
224
225
  segments:
225
226
  - 0
226
- hash: -4221078928752285961
227
+ hash: 2228522700796728917
227
228
  requirements: []
228
229
  rubyforge_project:
229
230
  rubygems_version: 1.8.11
@@ -236,6 +237,7 @@ test_files:
236
237
  - spec/baton/consumer_manager_spec.rb
237
238
  - spec/baton/consumer_spec.rb
238
239
  - spec/baton/server_spec.rb
240
+ - spec/fixtures/config-multi.cfg
239
241
  - spec/fixtures/config.cfg
240
242
  - spec/fixtures/file
241
243
  - spec/fixtures/file.sum