baton 0.4.4 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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