rservicebus2 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +64 -0
  3. data/bin/return_messages_to_source_queue +114 -0
  4. data/bin/rsb_ctl +38 -0
  5. data/bin/rservicebus2 +14 -0
  6. data/bin/rservicebus2-create +107 -0
  7. data/bin/rservicebus2-init +104 -0
  8. data/bin/rservicebus2-transport +16 -0
  9. data/bin/send_empty_message +15 -0
  10. data/lib/rservicebus.rb +59 -0
  11. data/lib/rservicebus/agent.rb +54 -0
  12. data/lib/rservicebus/appresource.rb +65 -0
  13. data/lib/rservicebus/appresource/dir.rb +29 -0
  14. data/lib/rservicebus/appresource/file.rb +8 -0
  15. data/lib/rservicebus/appresource/fluiddb.rb +24 -0
  16. data/lib/rservicebus/appresource_configure.rb +33 -0
  17. data/lib/rservicebus/audit.rb +28 -0
  18. data/lib/rservicebus/circuitbreaker.rb +79 -0
  19. data/lib/rservicebus/config.rb +168 -0
  20. data/lib/rservicebus/cron_manager.rb +76 -0
  21. data/lib/rservicebus/endpointmapping.rb +72 -0
  22. data/lib/rservicebus/errormessage.rb +14 -0
  23. data/lib/rservicebus/handler_loader.rb +162 -0
  24. data/lib/rservicebus/handler_manager.rb +131 -0
  25. data/lib/rservicebus/helper_functions.rb +85 -0
  26. data/lib/rservicebus/host.rb +487 -0
  27. data/lib/rservicebus/message.rb +78 -0
  28. data/lib/rservicebus/message/statisticoutput.rb +7 -0
  29. data/lib/rservicebus/message/subscription.rb +10 -0
  30. data/lib/rservicebus/message/verboseoutput.rb +7 -0
  31. data/lib/rservicebus/monitor.rb +61 -0
  32. data/lib/rservicebus/monitor/csvdir.rb +52 -0
  33. data/lib/rservicebus/monitor/dir.rb +139 -0
  34. data/lib/rservicebus/monitor/dirnotifier.rb +101 -0
  35. data/lib/rservicebus/monitor/message.rb +11 -0
  36. data/lib/rservicebus/monitor/xmldir.rb +11 -0
  37. data/lib/rservicebus/monitor_configure.rb +71 -0
  38. data/lib/rservicebus/mq.rb +98 -0
  39. data/lib/rservicebus/mq/beanstalk.rb +72 -0
  40. data/lib/rservicebus/resource_manager.rb +69 -0
  41. data/lib/rservicebus/saga/base.rb +17 -0
  42. data/lib/rservicebus/saga/data.rb +20 -0
  43. data/lib/rservicebus/saga/manager.rb +128 -0
  44. data/lib/rservicebus/saga_loader.rb +118 -0
  45. data/lib/rservicebus/saga_storage.rb +18 -0
  46. data/lib/rservicebus/saga_storage/dir.rb +87 -0
  47. data/lib/rservicebus/saga_storage/inmemory.rb +37 -0
  48. data/lib/rservicebus/sendat_manager.rb +33 -0
  49. data/lib/rservicebus/sendat_storage.rb +20 -0
  50. data/lib/rservicebus/sendat_storage/file.rb +37 -0
  51. data/lib/rservicebus/sendat_storage/inmemory.rb +20 -0
  52. data/lib/rservicebus/state_manager.rb +30 -0
  53. data/lib/rservicebus/state_storage.rb +18 -0
  54. data/lib/rservicebus/state_storage/dir.rb +66 -0
  55. data/lib/rservicebus/state_storage/inmemory.rb +25 -0
  56. data/lib/rservicebus/statistic_manager.rb +86 -0
  57. data/lib/rservicebus/stats.rb +68 -0
  58. data/lib/rservicebus/subscription_manager.rb +31 -0
  59. data/lib/rservicebus/subscription_storage.rb +39 -0
  60. data/lib/rservicebus/subscription_storage/file.rb +42 -0
  61. data/lib/rservicebus/subscription_storage/redis.rb +69 -0
  62. data/lib/rservicebus/subscription_storage_configure.rb +19 -0
  63. data/lib/rservicebus/test.rb +2 -0
  64. data/lib/rservicebus/test/bus.rb +32 -0
  65. data/lib/rservicebus/transporter.rb +142 -0
  66. data/lib/rservicebus/usermessage/withpayload.rb +10 -0
  67. metadata +184 -0
@@ -0,0 +1,25 @@
1
+ module RServiceBus
2
+ # StateStorage InMemory
3
+ class StateStorageInMemory
4
+ def initialize(_uri)
5
+ @hash = {}
6
+ end
7
+
8
+ def begin
9
+ @list = []
10
+ end
11
+
12
+ def get(handler)
13
+ hash = @hash[handler.class.name]
14
+ @list << Hash['name', handler.class.name, 'hash', hash]
15
+
16
+ hash
17
+ end
18
+
19
+ def commit
20
+ @list.each do |e|
21
+ @hash[e['name']] = e['hash']
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,86 @@
1
+ module RServiceBus
2
+ # Used to collect various run time stats for runtime reporting
3
+ class StatisticManager
4
+ attr_accessor :output
5
+
6
+ def initialize(host)
7
+ @host = host
8
+ @hash = {}
9
+
10
+ @total_processed = 0
11
+ @total_errored = 0
12
+ @total_sent = 0
13
+ @total_published = 0
14
+ @total_reply = 0
15
+
16
+ @total_by_message_type = {}
17
+
18
+ @output = !RServiceBus.get_value('VERBOSE', nil).nil?
19
+ @max_stat_output_countdown =
20
+ RServiceBus.get_value('STAT_OUTPUT_COUNTDOWN', '1').to_i
21
+ @stat_output_countdown = 0
22
+ end
23
+
24
+ def inc_total_processed
25
+ @total_processed += 1
26
+ end
27
+
28
+ def inc_total_errored
29
+ @total_errored += 1
30
+ end
31
+
32
+ def inc_total_sent
33
+ @total_sent += 1
34
+ end
35
+
36
+ def inc_total_published
37
+ @total_published += 1
38
+ end
39
+
40
+ def inc_total_reply
41
+ @total_reply += 1
42
+ end
43
+
44
+ def inc(key)
45
+ @hash[key] = 0 if @hash[key].nil?
46
+ @hash[key] += 1
47
+ end
48
+
49
+ def inc_message_type(class_name)
50
+ @total_by_message_type[class_name] = 0 if @total_by_message_type[class_name].nil?
51
+ @total_by_message_type[class_name] += 1
52
+ end
53
+
54
+ def get_for_reporting_2
55
+ return unless @written == false
56
+
57
+ @written = true
58
+ types = Hash.new(0)
59
+ ObjectSpace.each_object do |obj|
60
+ types[obj.class] += 1
61
+ end
62
+
63
+ types
64
+ end
65
+
66
+ def get_for_reporting_9
67
+ "T:#{@total_processed};" \
68
+ "E:#{@total_errored};" \
69
+ "S:#{@total_sent};" \
70
+ "P:#{@total_published};" \
71
+ "R:#{@total_reply}"
72
+ end
73
+
74
+ def report
75
+ @host.log(get_for_reporting_9) if @output
76
+ end
77
+
78
+ def tick
79
+ @stat_output_countdown -= 1
80
+ return unless @stat_output_countdown <= 0
81
+
82
+ report
83
+ @stat_output_countdown = @max_stat_output_countdown
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,68 @@
1
+ module RServiceBus
2
+ # Used to collect various run time stats for runtime reporting
3
+ class Stats
4
+ def initialize
5
+ @hash = {}
6
+
7
+ @total_processed = 0
8
+ @total_errored = 0
9
+ @total_sent = 0
10
+ @total_published = 0
11
+ @total_reply = 0
12
+
13
+ @total_by_message_type = {}
14
+
15
+ @written = false
16
+ end
17
+
18
+ def inc_total_processed
19
+ @total_processed += 1
20
+ end
21
+
22
+ def inc_total_errored
23
+ @total_errored += 1
24
+ end
25
+
26
+ def inc_total_sent
27
+ @total_sent += 1
28
+ end
29
+
30
+ def inc_total_published
31
+ @total_published += 1
32
+ end
33
+
34
+ def inc_total_reply
35
+ @total_reply += 1
36
+ end
37
+
38
+ def inc(key)
39
+ @hash[key] = 0 if @hash[key].nil?
40
+ @hash[key] += 1
41
+ end
42
+
43
+ def inc_message_type(class_name)
44
+ @total_by_message_type[class_name] = 0 if @total_by_message_type[class_name].nil?
45
+ @total_by_message_type[class_name] += 1
46
+ end
47
+ end
48
+
49
+ def get_for_reporting_2
50
+ return unless @written == false
51
+
52
+ @written = true
53
+ types = Hash.new(0)
54
+ ObjectSpace.each_object do |obj|
55
+ types[obj.class] += 1
56
+ end
57
+
58
+ types
59
+ end
60
+
61
+ def get_for_reporting
62
+ "T:#{@total_processed};
63
+ E:#{@total_errored};
64
+ S:#{@total_sent};
65
+ P:#{@total_published};
66
+ R:#{@total_reply}"
67
+ end
68
+ end
@@ -0,0 +1,31 @@
1
+ module RServiceBus
2
+ # Subscription Manager
3
+ class SubscriptionManager
4
+ def initialize(subscription_storage)
5
+ @subscription_storage = subscription_storage
6
+ @subscriptions = @subscription_storage.get_all
7
+ end
8
+
9
+ # Get subscriptions for given eventName
10
+ def get(event_name)
11
+ subscriptions = @subscriptions[event_name]
12
+ if subscriptions.nil?
13
+ RServiceBus.log "No subscribers for event, #{event_name}"
14
+ RServiceBus.log "If there should be, ensure you have the appropriate evironment variable set, eg MESSAGE_ENDPOINT_MAPPINGS=#{event_name}:<Queue Name>"
15
+ return []
16
+ end
17
+
18
+ subscriptions
19
+ end
20
+
21
+ def add(event_name, queue_name)
22
+ RServiceBus.log 'Adding subscription for, ' +
23
+ event_name + ', to, ' + queue_name
24
+ @subscriptions = @subscription_storage.add(event_name, queue_name)
25
+ end
26
+
27
+ def remove(event_name, queue_name)
28
+ fail 'Method, remove, needs to be implemented for this subscription storage'
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,39 @@
1
+ require 'uri'
2
+
3
+ module RServiceBus
4
+ # Base class for subscription storage
5
+ class SubscriptionStorage
6
+ # Constructor
7
+ # @param [String] app_name Name of the application, which is used as a
8
+ # Namespace
9
+ # @param [String] uri a location for the resource to which we will attach,
10
+ # eg redis://127.0.0.1/foo
11
+ def initialize(app_name, uri)
12
+ @app_name = app_name
13
+ @uri = uri
14
+ end
15
+
16
+ # Get a list of all subscription, as an Array
17
+ def get_all
18
+ fail 'Method, get_all, needs to be implemented for SubscriptionStorage'
19
+ end
20
+
21
+ # Add a new subscription
22
+ # @param [String] event_name Name of the event for which the subscriber
23
+ # has asked for notification
24
+ # @param [String] queue_name the queue to which the event should be sent
25
+ def add(_event_name, _queue_name)
26
+ fail 'Method, add, needs to be implemented for this subscription storage'
27
+ end
28
+
29
+ # Remove an existing subscription
30
+ #
31
+ # @param [String] event_name Name of the event for which the subscriber
32
+ # has asked for notification
33
+ # @param [String] queue_name the queue to which the event should be sent
34
+ def remove(_event_name, _queue_name)
35
+ fail 'Method, remove, needs to be implemented for this subscription
36
+ storage'
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,42 @@
1
+ module RServiceBus
2
+ # Implementation of Subscription Storage to Redis
3
+ class SubscriptionStorageFile < SubscriptionStorage
4
+ # Constructor
5
+ #
6
+ # @param [String] app_ame Name of the application, used as a Namespace
7
+ # @param [String] uri resource location to attach, eg redis://127.0.0.1/foo
8
+ def initialize(app_name, uri)
9
+ super(app_name, uri)
10
+ end
11
+
12
+ def get_all
13
+ RServiceBus.log 'Load subscriptions'
14
+ return {} unless File.exist?(@uri.path)
15
+
16
+ YAML.load(File.open(@uri.path))
17
+ end
18
+
19
+ def add(event_name, queue_name)
20
+ # s => subscriptions
21
+ if File.exist?(@uri.path)
22
+ s = YAML.load(File.open(@uri.path))
23
+ else
24
+ s = {}
25
+ end
26
+
27
+ s[event_name] = [] if s[event_name].nil?
28
+
29
+ s[event_name] << queue_name
30
+ s[event_name] = s[event_name].uniq
31
+
32
+ File.open(@uri.path, 'w') { |f| f.write(YAML.dump(s)) }
33
+
34
+ s
35
+ end
36
+
37
+ def remove(_event_name, _queue_name)
38
+ fail 'Method, remove, needs to be implemented for this
39
+ subscription storage'
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,69 @@
1
+ module RServiceBus
2
+
3
+ require 'redis'
4
+
5
+ #Implementation of Subscription Storage to Redis
6
+ class SubscriptionStorage_Redis<SubscriptionStorage
7
+
8
+ @redis
9
+
10
+ # Constructor
11
+ #
12
+ # @param [String] appName Name of the application, which is used as a Namespace
13
+ # @param [String] uri a location for the resource to which we will attach, eg redis://127.0.0.1/foo
14
+ def initialize( appName, uri )
15
+ super(appName, uri)
16
+ port = uri.port.nil? ? 6379 : uri.port
17
+ @redis = Redis.new( :host=>uri.host, :port=>port )
18
+ end
19
+
20
+ def getAll
21
+ RServiceBus.log 'Load subscriptions'
22
+ begin
23
+ content = @redis.get( @appName + '.Subscriptions')
24
+ if content.nil? then
25
+ subscriptions = Hash.new
26
+ else
27
+ subscriptions = YAML::load(content)
28
+ end
29
+ return subscriptions
30
+ rescue Exception => e
31
+ puts 'Error connecting to redis'
32
+ if e.message == 'Redis::CannotConnectError' ||
33
+ e.message == 'Redis::ECONNREFUSED' then
34
+ puts '***Most likely, redis is not running. Start redis, and try running this again.'
35
+ else
36
+ puts e.message
37
+ puts e.backtrace
38
+ end
39
+ abort()
40
+ end
41
+ end
42
+
43
+ def add( eventName, queueName )
44
+ content = @redis.get( @appName + '.Subscriptions')
45
+ if content.nil? then
46
+ subscriptions = Hash.new
47
+ else
48
+ subscriptions = YAML::load(content)
49
+ end
50
+
51
+ if subscriptions[eventName].nil? then
52
+ subscriptions[eventName] = Array.new
53
+ end
54
+
55
+ subscriptions[eventName] << queueName
56
+ subscriptions[eventName] = subscriptions[eventName].uniq
57
+
58
+ @redis.set( @appName + '.Subscriptions', YAML::dump(subscriptions ) )
59
+
60
+ return subscriptions
61
+ end
62
+
63
+ def remove( eventName, queueName )
64
+ raise 'Method, remove, needs to be implemented for this subscription storage'
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,19 @@
1
+ require 'uri'
2
+ module RServiceBus
3
+ # Configure SubscriptionStorage for an rservicebus host
4
+ class ConfigureSubscriptionStorage
5
+ def get(app_name, uri_string)
6
+ uri = URI.parse(uri_string)
7
+
8
+ case uri.scheme
9
+ when 'file'
10
+ require 'rservicebus/subscription_storage/file'
11
+ s = SubscriptionStorageFile.new(app_name, uri)
12
+ else
13
+ abort("Scheme, #{uri.scheme}, not recognised when configuring
14
+ subscription storage, #{uri_string}")
15
+ end
16
+ s
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,2 @@
1
+ require 'rservicebus/test/bus'
2
+ require 'rservicebus/test/redis'
@@ -0,0 +1,32 @@
1
+ module RServiceBus
2
+ # Test Bus
3
+ class TestBus
4
+ attr_accessor :publish_list, :send_list, :reply_list, :log_list, :sagaData
5
+
6
+ def initialize
7
+ @publish_list = []
8
+ @send_list = []
9
+ @reply_list = []
10
+ @log_list = []
11
+ end
12
+
13
+ def publish(msg)
14
+ @publish_list << msg
15
+ end
16
+
17
+ def send(msg)
18
+ @send_list << msg
19
+ end
20
+
21
+ def reply(msg)
22
+ @reply_list << msg
23
+ end
24
+
25
+ def log(string, verbose = false)
26
+ item = {}
27
+ item['string'] = string
28
+ item['verbose'] = verbose
29
+ @log_list << item
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,142 @@
1
+ require 'beanstalk-client'
2
+ require 'rservicebus'
3
+ require 'net/ssh/gateway'
4
+
5
+ module RServiceBus
6
+ class CouldNotConnectToDestination < StandardError
7
+ end
8
+
9
+ # TODO: Poison Message? Can I bury with timeout in beanstalk ?
10
+ # Needs to end up on an error queue, destination queue may be down.
11
+ class Transporter
12
+ def get_value(name, default = nil)
13
+ value = (ENV[name].nil? || ENV[name] == '') ? default : ENV[name]
14
+ RServiceBus.log "Env value: #{name}: #{value}"
15
+ value
16
+ end
17
+
18
+ def connect_to_source_beanstalk
19
+ source_queue_name = get_value('SOURCE_QUEUE_NAME', 'transport-out')
20
+ source_url = get_value('SOURCE_URL', '127.0.0.1:11300')
21
+ @source = Beanstalk::Pool.new([source_url])
22
+ @source.watch source_queue_name
23
+
24
+ RServiceBus.log "Connected to, #{source_queue_name}@#{source_url}"
25
+
26
+ rescue StandardError => e
27
+ puts 'Error connecting to Beanstalk'
28
+ puts "Host string, #{sourceUrl}"
29
+ if e.message == 'Beanstalk::NotConnected'
30
+ puts '***Most likely, beanstalk is not running. Start beanstalk, and try running this again.'
31
+ puts "***If you still get this error, check beanstalk is running at, #{sourceUrl}"
32
+ else
33
+ puts e.message
34
+ puts e.backtrace
35
+ end
36
+ abort
37
+ end
38
+
39
+ def disconnect
40
+ RServiceBus.log "Disconnect from,
41
+ #{@remote_user_name}@#{@remote_host_name}/#{@remote_queue_name}"
42
+ @gateway.shutdown! unless @gateway.nil?
43
+ @gateway = nil
44
+ @remote_host_name = nil
45
+
46
+ @destination.close unless @destination.nil?
47
+ @destination = nil
48
+
49
+ @remote_user_name = nil
50
+ @remote_queue_name = nil
51
+ end
52
+
53
+ def connect(remote_host_name)
54
+ RServiceBus.rlog "connect called, #{remote_host_name}"
55
+ if @gateway.nil? || remoteHostName != @remote_host_name || @destination.nil?
56
+ disconnect
57
+ end
58
+
59
+ if @gateway.nil?
60
+ # Get destination url from job
61
+ @remote_host_name = remote_host_name
62
+ @remote_user_name = get_value("REMOTE_USER_#{remote_host_name.upcase}")
63
+ if @remote_user_name.nil?
64
+ RServiceBus.log "**** Username not specified for Host, #{remoteHostName}"
65
+ RServiceBus.log "**** Add an environment variable of the form, REMOTE_USER_#{remoteHostName.upcase}=[USERNAME]"
66
+ abort
67
+ end
68
+
69
+ @local_port = get_value('LOCAL_PORT', 27018).to_i
70
+ RServiceBus.rlog "Local Port: #{@local_port}"
71
+ begin
72
+ RServiceBus.log "Connect SSH, #{@remote_user_name}@#{@remoteHostName}"
73
+ # Open port 27018 to forward to 127.0.0.11300 on the remote host
74
+ @gateway = Net::SSH::Gateway.new(@remote_host_name, @remote_user_name)
75
+ @gateway.open('127.0.0.1', 11300, @local_port)
76
+ RServiceBus.log "Connected to SSH, #{@remote_user_name}@#{@remote_host_name}"
77
+
78
+ rescue Errno::EADDRINUSE
79
+ puts "*** Local transport port in use, #{@local_port}"
80
+ puts "*** Change local transport port, #{@localPort}, using format, LOCAL_PORT=#{@localPort+1}"
81
+ abort
82
+ rescue Errno::EACCES
83
+ puts "*** Local transport port specified, #{@local_port}, needs sudo access"
84
+ puts '*** Change local transport port using format, LOCAL_PORT=27018'
85
+ abort
86
+ end
87
+
88
+ begin
89
+ destination_url = "127.0.0.1:#{@local_port}"
90
+ RServiceBus.rlog "Connect to Remote Beanstalk, #{destination_url}"
91
+ @destination = Beanstalk::Pool.new([destinationUrl])
92
+ RServiceBus.rlog "Connected to Remote Beanstalk, #{destination_url}"
93
+ rescue StandardError => e
94
+ if e.message == 'Beanstalk::NotConnected'
95
+ puts "***Could not connect to destination, check beanstalk is running at, #{destination_url}"
96
+ raise CouldNotConnectToDestination
97
+ end
98
+ raise
99
+ end
100
+ end
101
+ end
102
+
103
+ def process
104
+ # Get the next job from the source queue
105
+ job = @source.reserve @timeout
106
+ msg = YAML.load(job.body)
107
+
108
+ connect(msg.remote_host_name)
109
+
110
+ @remote_queue_name = msg.remote_queue_name
111
+ RServiceBus.rlog "Put msg, #{msg.remote_queue_name}"
112
+ @destination.use(msg.remote_queue_name)
113
+ @destination.put(job.body)
114
+ RServiceBus.log "Msg put, #{msg.remote_queue_name}"
115
+
116
+ unless ENV['AUDIT_QUEUE_NAME'].nil?
117
+ @source.use ENV['AUDIT_QUEUE_NAME']
118
+ @source.put job.body
119
+ end
120
+ # remove job
121
+ job.delete
122
+
123
+ RServiceBus.log "Job sent to, #{@remote_user_name}@#{@remote_host_name}/#{@remote_queue_name}"
124
+ rescue StandardError => e
125
+ disconnect
126
+ if e.message == 'TIMED_OUT'
127
+ RServiceBus.rlog 'No Msg'
128
+ return
129
+ end
130
+ raise e
131
+ end
132
+
133
+ def run
134
+ @timeout = get_value('TIMEOUT', 5)
135
+ connectToSourceBeanstalk
136
+ while true
137
+ process
138
+ end
139
+ disconnect_from_remote_ssh
140
+ end
141
+ end
142
+ end