rservicebus2 0.0.1

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.
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