mbus 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.mediawiki +169 -0
- data/Rakefile +24 -0
- data/bin/console +11 -0
- data/bin/messagebus_swarm +77 -0
- data/lib/messagebus.rb +62 -0
- data/lib/messagebus/client.rb +166 -0
- data/lib/messagebus/cluster_map.rb +161 -0
- data/lib/messagebus/connection.rb +118 -0
- data/lib/messagebus/consumer.rb +447 -0
- data/lib/messagebus/custom_errors.rb +37 -0
- data/lib/messagebus/dottable_hash.rb +113 -0
- data/lib/messagebus/error_status.rb +42 -0
- data/lib/messagebus/logger.rb +45 -0
- data/lib/messagebus/message.rb +168 -0
- data/lib/messagebus/messagebus_types.rb +107 -0
- data/lib/messagebus/producer.rb +187 -0
- data/lib/messagebus/swarm.rb +49 -0
- data/lib/messagebus/swarm/controller.rb +296 -0
- data/lib/messagebus/swarm/drone.rb +195 -0
- data/lib/messagebus/swarm/drone/logging_worker.rb +53 -0
- data/lib/messagebus/validations.rb +68 -0
- data/lib/messagebus/version.rb +36 -0
- data/messagebus.gemspec +29 -0
- data/spec/messagebus/client_spec.rb +157 -0
- data/spec/messagebus/cluster_map_spec.rb +178 -0
- data/spec/messagebus/consumer_spec.rb +338 -0
- data/spec/messagebus/dottable_hash_spec.rb +137 -0
- data/spec/messagebus/message_spec.rb +93 -0
- data/spec/messagebus/producer_spec.rb +147 -0
- data/spec/messagebus/swarm/controller_spec.rb +73 -0
- data/spec/messagebus/validations_spec.rb +71 -0
- data/spec/spec_helper.rb +10 -0
- data/vendor/gems/stomp.rb +23 -0
- data/vendor/gems/stomp/client.rb +360 -0
- data/vendor/gems/stomp/connection.rb +583 -0
- data/vendor/gems/stomp/errors.rb +39 -0
- data/vendor/gems/stomp/ext/hash.rb +24 -0
- data/vendor/gems/stomp/message.rb +68 -0
- metadata +138 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 689df9b9f0b86245507faeda6239d9ca24ff2cf1
|
4
|
+
data.tar.gz: 6e95ce8920e6f92951dc28dd967e7049d16ad160
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9d8ada5f134ebf4c992d831ac28ad3cc786c40172c22e1279668afbf774858daeb8f7f9b03dd55ad549cff0ab91b36972c74630e16535f8735ea97b6ed80d19c
|
7
|
+
data.tar.gz: cdfe47c4cfbaa25d92a072cd67776b2aa0ff79f145223176c71764154a4845f3be32d0ff2fed93d4c1f357d2d7b0d4dcbcddb2fb37fc6c7ab39bc2c86c27e4a6
|
data/README.mediawiki
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
= Messagebus =
|
2
|
+
|
3
|
+
A gem for publishing and consuming hornetq messagebus messages.
|
4
|
+
|
5
|
+
== Installation ==
|
6
|
+
|
7
|
+
$ gem install mbus
|
8
|
+
|
9
|
+
== Dependencies ==
|
10
|
+
|
11
|
+
This Gem depends upon the following:
|
12
|
+
|
13
|
+
=== Runtime ===
|
14
|
+
|
15
|
+
* messagebus (vendored an old version for now)
|
16
|
+
* thrift
|
17
|
+
* json
|
18
|
+
|
19
|
+
=== Development & Tests ===
|
20
|
+
|
21
|
+
* bundle install
|
22
|
+
* Execute rspec spec
|
23
|
+
|
24
|
+
== Configuration ==
|
25
|
+
|
26
|
+
The messagebus is configured via a single yaml file. The configuration fields are defined below and an
|
27
|
+
example of a full configuration also provided.
|
28
|
+
|
29
|
+
* enable_auto_init_connections: turn on producer connections once initialized
|
30
|
+
* log_file: path for log
|
31
|
+
* log_level: logger level minimum
|
32
|
+
* logger: pass a logger directly to the messagebus client
|
33
|
+
* worker_log_file: path for worker log
|
34
|
+
* cluster_defaults
|
35
|
+
** user: hornetq user
|
36
|
+
** passwd: hornetq password
|
37
|
+
** receipt_wait_timeout_ms: TODO
|
38
|
+
** conn_lifetime_sec: TODO
|
39
|
+
* clusters: array of haproxy clusters
|
40
|
+
** type: producer-cluster or consumer-cluster
|
41
|
+
** address: host and port of haproxy delimited by colon
|
42
|
+
** destinations: array of queue and topic destinations
|
43
|
+
* swarm_config
|
44
|
+
** fork: true or false -- whether to use forks or threads when booting drones
|
45
|
+
* workers
|
46
|
+
** destination: the destination name
|
47
|
+
** worker: the worker class to process messages with
|
48
|
+
** subscription_id: swarm_drone_run_spec_id
|
49
|
+
** ack_on_error: whether to send an ack for a job that failed
|
50
|
+
** drones: number of drones to boot up for parallel processing
|
51
|
+
|
52
|
+
'''Example config'''
|
53
|
+
enable_auto_init_connections: true
|
54
|
+
log_file: log/messagebus-client.log
|
55
|
+
worker_log_file: log/messagebus-consumer.log
|
56
|
+
|
57
|
+
:swarm_config:
|
58
|
+
# :fork: true
|
59
|
+
|
60
|
+
:workers:
|
61
|
+
-
|
62
|
+
:destination: jms.topic.testTopic2
|
63
|
+
:worker: SimpleDroneRunSpecWorker
|
64
|
+
:subscription_id: swarm_drone_run_spec_id
|
65
|
+
|
66
|
+
:ack_on_error: false
|
67
|
+
:drones: 1
|
68
|
+
|
69
|
+
:cluster_defaults:
|
70
|
+
:user: guest
|
71
|
+
:passwd: guest
|
72
|
+
:receipt_wait_timeout_ms: 1500
|
73
|
+
:conn_lifetime_sec: 300
|
74
|
+
:enable_dynamic_serverlist_fetch: true
|
75
|
+
|
76
|
+
clusters:
|
77
|
+
-
|
78
|
+
name: orders-messagebus-cluster
|
79
|
+
producer_address: localhost:61613
|
80
|
+
consumer_address: localhost:61613
|
81
|
+
destinations:
|
82
|
+
- jms.topic.testTopic2
|
83
|
+
|
84
|
+
== Getting Started ==
|
85
|
+
|
86
|
+
You will find an example listed of loading a configuration, instantiation of a client, and
|
87
|
+
finally invocation of the publish method. There are three different message types that can
|
88
|
+
be published on the bus, string, binary, or json. An example of each are listed with concrete
|
89
|
+
code to use.
|
90
|
+
|
91
|
+
In its current state, the messagebus gem should be vendored into your application. This will
|
92
|
+
change once the internal rubygems server is integrated into the company. For now, unpack the
|
93
|
+
gem and include "thrift" 0.9.0 into your Gemfile next to the messagebus declaration.
|
94
|
+
|
95
|
+
=== Edit Gemfile ===
|
96
|
+
|
97
|
+
gem "thrift", "0.9.0"
|
98
|
+
gem "messagebus", "x.x.x", :path => "vendor/gems/messagebus-x.x.x", :require => "messagebus"
|
99
|
+
|
100
|
+
|
101
|
+
=== Bundle your gems ===
|
102
|
+
|
103
|
+
$ bundle
|
104
|
+
|
105
|
+
== Producing Messages ==
|
106
|
+
=== Run interactive ruby ===
|
107
|
+
|
108
|
+
$ irb
|
109
|
+
|
110
|
+
ruby>
|
111
|
+
require "messagebus" # Notice this will happen by default in the bundler
|
112
|
+
|
113
|
+
ruby>
|
114
|
+
binary_to_publish = "\xfe\x3e\x5e"
|
115
|
+
config = YAML.load_file("./config/messagebus.yml")
|
116
|
+
client = Messagebus::Client.new(config.merge(:logger => Logger.new("a/directory/to/my/file.log")))
|
117
|
+
client.start
|
118
|
+
client.publish "jms.queue.testQueue1", binary_to_publish
|
119
|
+
|
120
|
+
ruby>
|
121
|
+
string_to_publish = "the quick brown fox jumped over the lazy dogs back"
|
122
|
+
config = YAML.load_file("./config/messagebus.yml")
|
123
|
+
client = Messagebus::Client.new(config.merge(:logger => Logger.new("a/directory/to/my/file.log")))
|
124
|
+
client.publish "jms.queue.testQueue1", string_to_publish
|
125
|
+
|
126
|
+
ruby>
|
127
|
+
hash_to_publish = { :ruby => { :loves => :the_bus } }
|
128
|
+
config = YAML.load_file("./config/messagebus.yml")
|
129
|
+
client = Messagebus::Client.new(config.merge(:logger => Logger.new("a/directory/to/my/file.log")))
|
130
|
+
client.publish "jms.queue.testQueue1", hash_to_publish
|
131
|
+
|
132
|
+
ruby>
|
133
|
+
object_to_publish = DomainObjectThatRespondsToToJson # object_to_publish.to_json will happen automatically
|
134
|
+
config = YAML.load_file("./config/messagebus.yml")
|
135
|
+
client = Messagebus::Client.new(config.merge(:logger => Logger.new("a/directory/to/my/file.log")))
|
136
|
+
client.publish "jms.queue.testQueue1", object_to_publish
|
137
|
+
|
138
|
+
=== Watch Tail Processing Log ===
|
139
|
+
|
140
|
+
The tail will start displaying new log messages.
|
141
|
+
|
142
|
+
$ tail -f log/messagebus-client.log
|
143
|
+
|
144
|
+
|
145
|
+
== Consuming messages ==
|
146
|
+
You have 2 options. Option 1 is write your own consumer class. See [[https://github.com/groupon/Message-Bus/blob/master/mbus-ruby/examples/consumer_topic_example.rb|consumer_topic_example.rb]]
|
147
|
+
for how to write your own consumer.
|
148
|
+
|
149
|
+
Your other option is to use the Message Swarm code. Try examples/swarm_example.sh. See [[https://github.com/groupon/Message-Bus/wiki/Swarm-Consumer|Swarm Guide]] for more on that.
|
150
|
+
|
151
|
+
== More detail needed? ==
|
152
|
+
|
153
|
+
Contact us via email! dpe@groupon.com
|
154
|
+
|
155
|
+
If something is not behaving intuitively, it is a bug and should be reported.
|
156
|
+
Report it here: https://github.groupon.com/data-infrastructure/ruby-messagebus
|
157
|
+
|
158
|
+
== Note on Patches/Pull Requests ==
|
159
|
+
|
160
|
+
* Fork the project.
|
161
|
+
* Make your feature addition or bug fix.
|
162
|
+
* Commit, do not mess with rakefile, version, or history.
|
163
|
+
* Send me a pull request. Bonus points for topic branches.
|
164
|
+
|
165
|
+
== Copyright ==
|
166
|
+
|
167
|
+
Copyright (c) 2011 Groupon. Released under the MIT License.
|
168
|
+
|
169
|
+
See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rubygems/package_task"
|
3
|
+
require "rspec/core/rake_task"
|
4
|
+
|
5
|
+
SPEC = begin
|
6
|
+
file = File.expand_path(File.dirname(__FILE__) + '/messagebus.gemspec')
|
7
|
+
eval(File.read(file), binding, file)
|
8
|
+
end
|
9
|
+
|
10
|
+
Gem::PackageTask.new(SPEC) {}
|
11
|
+
|
12
|
+
desc "Run all specs"
|
13
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
14
|
+
t.rspec_opts = %w[--color --format=progress]
|
15
|
+
t.pattern = 'spec/**/*_spec.rb'
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Run code coverage"
|
19
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
20
|
+
t.rspec_opts = %w[--color --format=progress]
|
21
|
+
t.rcov = true
|
22
|
+
t.rcov_opts = %w[--exclude='gems,spec']
|
23
|
+
t.pattern = 'spec/**/*_spec.rb'
|
24
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
|
5
|
+
require 'messagebus'
|
6
|
+
require 'messagebus/swarm/controller'
|
7
|
+
|
8
|
+
options = {
|
9
|
+
:requires => [],
|
10
|
+
:configuration_source => Messagebus::Swarm::Controller::ConfigurationSource.new(:default, nil)
|
11
|
+
}
|
12
|
+
|
13
|
+
parser = OptionParser.new do |opts|
|
14
|
+
opts.banner = "Usage: swarm [options] COMMAND"
|
15
|
+
|
16
|
+
opts.separator ""
|
17
|
+
opts.separator "Options:"
|
18
|
+
|
19
|
+
opts.on("--config_path PATH", "A path to a yaml configuration file") do |config_path|
|
20
|
+
options[:configuration_source] = Messagebus::Swarm::Controller::ConfigurationSource.new(:path, config_path)
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on("--config_eval RUBY_CODE", "Ruby that evaluates to a configuration hash. This is ran after any requires") do |config_eval|
|
24
|
+
options[:configuration_source] = Messagebus::Swarm::Controller::ConfigurationSource.new(:eval, config_eval)
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-h", "--help", "Show help message") do
|
28
|
+
puts opts
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("-r", "--require FILE", "A file to require before starting the swarm. Repeatable.") do |file|
|
32
|
+
options[:requires] << file
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("--pidfile PID_FILE", "A file to write the PID to") do |file|
|
36
|
+
options[:pidfile] = file
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.separator ""
|
40
|
+
opts.separator "Commands:"
|
41
|
+
opts.separator " start Start all workers in the configuration"
|
42
|
+
opts.separator " start DESTINATION COUNT Start COUNT workers for DESTINATION swarm listeners"
|
43
|
+
opts.separator " stop pid Kill a swarm"
|
44
|
+
opts.separator ""
|
45
|
+
end
|
46
|
+
|
47
|
+
parser.parse!
|
48
|
+
|
49
|
+
Messagebus::Swarm::Controller.require_files(options[:requires])
|
50
|
+
if pidfile = options[:pidfile]
|
51
|
+
pid = Process.pid
|
52
|
+
Messagebus::Swarm::Controller.write_pid(pidfile)
|
53
|
+
at_exit do
|
54
|
+
# we need this check to make sure we only bother doing this if
|
55
|
+
# we are the parent process that's shutting down
|
56
|
+
# at_exit is carried down when forking
|
57
|
+
Messagebus::Swarm::Controller.delete_pid(pidfile) if Process.pid == pid
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
case ARGV[0]
|
62
|
+
when 'start'
|
63
|
+
destination_name, drone_count = ARGV[1], ARGV[2]
|
64
|
+
|
65
|
+
log_file = options[:configuration_source].configuration_hash["worker_log_file"]
|
66
|
+
logger = log_file ? Logger.new(log_file) : Messagebus::Client.logger
|
67
|
+
|
68
|
+
Messagebus::Swarm::Controller.start(options[:configuration_source], logger, destination_name, drone_count)
|
69
|
+
exit(0)
|
70
|
+
when 'stop'
|
71
|
+
pid = ARGV[1] or raise "Must specify a pid of the process to stop"
|
72
|
+
Messagebus::Swarm::Controller.stop(pid.to_i)
|
73
|
+
exit(0)
|
74
|
+
else
|
75
|
+
puts parser.help
|
76
|
+
exit(1)
|
77
|
+
end
|
data/lib/messagebus.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Copyright (c) 2012, Groupon, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions
|
6
|
+
# are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# Redistributions in binary form must reproduce the above copyright
|
12
|
+
# notice, this list of conditions and the following disclaimer in the
|
13
|
+
# documentation and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# Neither the name of GROUPON nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without
|
17
|
+
# specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
20
|
+
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
21
|
+
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
22
|
+
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
23
|
+
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
24
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
25
|
+
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
26
|
+
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
27
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
28
|
+
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
29
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
31
|
+
$:.unshift(File.join(File.dirname(__FILE__), "..", "vendor/gems"))
|
32
|
+
|
33
|
+
require "messagebus/version"
|
34
|
+
require 'messagebus/logger'
|
35
|
+
require 'messagebus/message'
|
36
|
+
require "messagebus/messagebus_types"
|
37
|
+
require 'messagebus/custom_errors'
|
38
|
+
require 'messagebus/error_status'
|
39
|
+
require 'messagebus/validations'
|
40
|
+
require 'messagebus/connection'
|
41
|
+
require 'messagebus/producer'
|
42
|
+
require 'messagebus/consumer'
|
43
|
+
require 'messagebus/cluster_map'
|
44
|
+
require 'messagebus/client'
|
45
|
+
|
46
|
+
require 'thrift'
|
47
|
+
require 'base64'
|
48
|
+
require 'stomp'
|
49
|
+
|
50
|
+
module Messagebus
|
51
|
+
# These are deprecated and not used anymore
|
52
|
+
DEST_TYPE_QUEUE = 'queue'
|
53
|
+
DEST_TYPE_TOPIC = 'topic'
|
54
|
+
|
55
|
+
ACK_TYPE_AUTO_CLIENT = 'autoClient'
|
56
|
+
ACK_TYPE_CLIENT = 'client'
|
57
|
+
|
58
|
+
LOG_DEFAULT_FILE = '/tmp/messagebus_client.log'
|
59
|
+
|
60
|
+
SERVER_REGEX = /^[a-zA-Z0-9\_.-]+:[0-9]+$/
|
61
|
+
end
|
62
|
+
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# Copyright (c) 2012, Groupon, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions
|
6
|
+
# are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# Redistributions in binary form must reproduce the above copyright
|
12
|
+
# notice, this list of conditions and the following disclaimer in the
|
13
|
+
# documentation and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# Neither the name of GROUPON nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without
|
17
|
+
# specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
20
|
+
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
21
|
+
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
22
|
+
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
23
|
+
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
24
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
25
|
+
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
26
|
+
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
27
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
28
|
+
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
29
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
31
|
+
require "messagebus/dottable_hash"
|
32
|
+
require "benchmark"
|
33
|
+
require "logger"
|
34
|
+
|
35
|
+
module Messagebus
|
36
|
+
class Client
|
37
|
+
class InvalidDestinationError < StandardError; end
|
38
|
+
class InitializationError < StandardError; end
|
39
|
+
|
40
|
+
attr_reader :config, :logger, :cluster_map, :last_reload_time
|
41
|
+
|
42
|
+
def self.start(config_hash)
|
43
|
+
client = new(config_hash)
|
44
|
+
client.start
|
45
|
+
|
46
|
+
if block_given?
|
47
|
+
begin
|
48
|
+
yield client
|
49
|
+
ensure
|
50
|
+
client.stop
|
51
|
+
end
|
52
|
+
end
|
53
|
+
client
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize(config_hash)
|
57
|
+
|
58
|
+
@@logger = if provided_logger = config_hash.delete(:logger)
|
59
|
+
provided_logger
|
60
|
+
elsif log_file = config_hash["log_file"]
|
61
|
+
Logger.new(log_file)
|
62
|
+
else
|
63
|
+
Logger.new(Messagebus::LOG_DEFAULT_FILE)
|
64
|
+
end
|
65
|
+
|
66
|
+
# This is required to do a deep clone of config hash object
|
67
|
+
@config = DottableHash.new(Marshal.load(Marshal.dump(config_hash)))
|
68
|
+
@config.merge!(@config.cluster_defaults) if @config.cluster_defaults
|
69
|
+
@@logger.level = Logger::Severity.const_get(@config.log_level.upcase) if @config.log_level
|
70
|
+
|
71
|
+
@enable_client_logger_thread_debugging = config.enable_client_logger_thread_debugging
|
72
|
+
|
73
|
+
logger.debug "Initializing Messagebus client."
|
74
|
+
@cluster_map = ClusterMap.new(@config)
|
75
|
+
#added for reloading config on interval
|
76
|
+
@last_reload_time = Time.now
|
77
|
+
end
|
78
|
+
|
79
|
+
# Starts up all the connections to the bus.
|
80
|
+
# Optionally takes a block to which it yields self. When the block is
|
81
|
+
# passed, it will auto close the connections after the block finishes.
|
82
|
+
def start
|
83
|
+
if @config.enable_auto_init_connections
|
84
|
+
logger.info "auto enable connections set, starting clusters."
|
85
|
+
@cluster_map.start
|
86
|
+
else
|
87
|
+
logger.info "Config['enable_auto_init_connections'] is false, will not start any messagebus producers."
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def stop
|
92
|
+
cluster_map.stop
|
93
|
+
end
|
94
|
+
|
95
|
+
def logger
|
96
|
+
@@logger ||= @config['log_file'] ? Logger.new(@config['log_file']) : Logger.new(Messagebus::LOG_DEFAULT_FILE)
|
97
|
+
end
|
98
|
+
|
99
|
+
def publish(destination_name, object, delay_ms = 0, safe = true, binary = false, headers = {})
|
100
|
+
|
101
|
+
if !(@config.enable_auto_init_connections)
|
102
|
+
logger.warn "Config['enable_auto_init_connections'] is false, not publishing destination_name=#{destination_name}, message_contents=#{object.inspect}"
|
103
|
+
false
|
104
|
+
else
|
105
|
+
producer = cluster_map.find(destination_name)
|
106
|
+
if producer.nil?
|
107
|
+
logger.error "Not publishing due to unconfigured destionation name. destination_name=#{destination_name}, message=#{object.inspect}"
|
108
|
+
raise InvalidDestinationError, "Destination #{destination_name} not found"
|
109
|
+
end
|
110
|
+
|
111
|
+
if binary
|
112
|
+
message = Messagebus::Message.create(object, nil, binary)
|
113
|
+
else
|
114
|
+
message = Messagebus::Message.create(object)
|
115
|
+
end
|
116
|
+
|
117
|
+
logger.info "Publishing to destination_name=#{destination_name}, message_id=#{message.message_id}, message_contents=#{object.inspect}"
|
118
|
+
|
119
|
+
begin
|
120
|
+
publish_result = nil
|
121
|
+
duration = Benchmark.realtime do
|
122
|
+
publish_result = producer.publish(destination_name, message, headers(delay_ms).merge(headers), safe)
|
123
|
+
end
|
124
|
+
duration = (duration * 1_000).round
|
125
|
+
|
126
|
+
if publish_result
|
127
|
+
logger.info "Message publishing to #{destination_name} took #{duration} result=success destination_name=#{destination_name}, message_id=#{message.message_id}, duration=#{duration}ms"
|
128
|
+
true
|
129
|
+
else
|
130
|
+
logger.error "Failed to publish message result=fail destination_name=#{destination_name}, message_id=#{message.message_id}, duration=#{duration}ms, message_contents=#{object.inspect}"
|
131
|
+
false
|
132
|
+
end
|
133
|
+
rescue => e
|
134
|
+
logger.error "Failed to publish message result=error destination_name=#{destination_name}, message_id=#{message.message_id}, duration=#{duration}ms, message_contents=#{object.inspect}, error=#{e.inspect}, backtrace=#{e.backtrace.join("|")}"
|
135
|
+
false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def reload_config_on_interval(config, interval = 300)
|
141
|
+
logger.info "Relaoding client configs after interval=#{interval}"
|
142
|
+
now = Time.now
|
143
|
+
if(now - @last_reload_time) >= interval
|
144
|
+
@cluster_map.update_config(config)
|
145
|
+
@last_reload_time = now
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def headers(delay)
|
150
|
+
headers = {}
|
151
|
+
unless delay == 0
|
152
|
+
schedule_time = (Time.now.to_i * 1000 + delay).to_s
|
153
|
+
headers.merge!({
|
154
|
+
Messagebus::Producer::SCHEDULED_DELIVERY_TIME_MS_HEADER => schedule_time
|
155
|
+
})
|
156
|
+
end
|
157
|
+
headers
|
158
|
+
end
|
159
|
+
|
160
|
+
class << self
|
161
|
+
def logger
|
162
|
+
@@logger ||= Logger.new(Messagebus::LOG_DEFAULT_FILE)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|