ap4r 0.3.1 → 0.3.2
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.
- data/CHANGELOG +17 -7
- data/MIT-LICENSE +1 -1
- data/README +4 -145
- data/Rakefile +50 -4
- data/lib/ap4r.rb +1 -1
- data/lib/ap4r/carrier.rb +107 -0
- data/lib/ap4r/dispatcher.rb +326 -0
- data/lib/ap4r/message_store_ext.rb +9 -5
- data/lib/ap4r/mongrel.rb +9 -4
- data/{script → lib/ap4r}/mongrel_ap4r.rb +1 -2
- data/lib/ap4r/multi_queue.rb +2 -1
- data/lib/ap4r/queue_manager_ext.rb +86 -200
- data/lib/ap4r/queue_manager_ext_debug.rb +15 -7
- data/lib/ap4r/retention_history.rb +3 -2
- data/lib/ap4r/script/base.rb +1 -1
- data/lib/ap4r/script/queue_manager_control.rb +1 -1
- data/lib/ap4r/script/setup.rb +1 -1
- data/lib/ap4r/script/workspace_generator.rb +2 -2
- data/lib/ap4r/start_with_log4r.rb +4 -1
- data/lib/ap4r/store_and_forward.rb +10 -6
- data/lib/ap4r/stored_message.rb +4 -3
- data/lib/ap4r/util/irm.rb +3 -3
- data/lib/ap4r/util/queue_client.rb +1 -1
- data/lib/ap4r/version.rb +2 -2
- data/rails_plugin/ap4r/lib/async_controller.rb +52 -41
- data/script/mongrel_ap4r +4 -0
- metadata +34 -8
- data/lib/ap4r/util/loc.rb +0 -12
- data/lib/ap4r/xxx_create_table_for_saf.rb +0 -21
- data/rails_plugin/ap4r/init.rb +0 -10
@@ -1,9 +1,9 @@
|
|
1
1
|
# Author:: Shunichi Shinohara
|
2
|
-
# Copyright:: Copyright (c)
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
|
-
module ReliableMsg
|
6
|
-
module MessageStore
|
5
|
+
module ReliableMsg #:nodoc:
|
6
|
+
module MessageStore #:nodoc:
|
7
7
|
class Base
|
8
8
|
|
9
9
|
cattr_accessor :use_mysql_extention
|
@@ -37,11 +37,15 @@ module ReliableMsg
|
|
37
37
|
end
|
38
38
|
|
39
39
|
if ReliableMsg::MessageStore::Base.use_mysql_extention
|
40
|
-
class Mysql
|
40
|
+
class Mysql #:nodoc:
|
41
41
|
alias original_query query
|
42
|
+
|
43
|
+
# In Ruby/MySQL, +query+ method does NOT care about a given block.
|
44
|
+
# To make it behave the same as MySQL/Ruby, this method adds iteration
|
45
|
+
# over query results.
|
42
46
|
def query(q, &block)
|
43
47
|
maybe_result = original_query(q, &block)
|
44
|
-
puts "Mysql extention: query called by #{q}"
|
48
|
+
puts "Mysql extention: query called by #{q}" if $DEBUG
|
45
49
|
puts "Mysql#query returns #{maybe_result}(class: #{maybe_result.class})." if $DEBUG
|
46
50
|
return maybe_result unless block && maybe_result.kind_of?(Mysql::Result)
|
47
51
|
begin
|
data/lib/ap4r/mongrel.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Author:: Shunichi Shinohara
|
2
|
-
# Copyright:: Copyright (c) 2007 Future Architect
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
5
|
require 'mongrel'
|
@@ -8,8 +8,10 @@ require 'cgi'
|
|
8
8
|
require 'ap4r'
|
9
9
|
|
10
10
|
module Ap4r
|
11
|
-
module Mongrel
|
12
11
|
|
12
|
+
module Mongrel #:nodoc:
|
13
|
+
|
14
|
+
# Gather controls AP4R server.
|
13
15
|
class Ap4rConfigurator < ::Mongrel::Configurator
|
14
16
|
|
15
17
|
def stop(needs_restart=false)
|
@@ -39,6 +41,7 @@ module Ap4r
|
|
39
41
|
|
40
42
|
# Implements a handler that can run AP4R.
|
41
43
|
# * If the requested exact PATH_INFO exists as a file then serve it.
|
44
|
+
# + (Second, access server information or queue/topic API) NOT IMPLEMENTED.
|
42
45
|
# * Finally, raise an exception.
|
43
46
|
#
|
44
47
|
# memo: want to use this handler to take information from AP4R server
|
@@ -47,11 +50,13 @@ module Ap4r
|
|
47
50
|
# TODO not yet implemented 2007/04/09 by shino
|
48
51
|
#
|
49
52
|
class Ap4rHandler < ::Mongrel::HttpHandler
|
50
|
-
STDERR.puts "CAUTION! This script is rather experimental."
|
51
53
|
attr_reader :files
|
52
54
|
@@file_only_methods = ["GET","HEAD"]
|
53
55
|
|
54
56
|
def initialize(options)
|
57
|
+
# TODO: needs various modes for easy operations 2007/05/02 by shino
|
58
|
+
# e.g. not to initialize message store, not to start dispatchers, etc.
|
59
|
+
|
55
60
|
# TODO what is "false" here? 2007/04/13 by shinohara
|
56
61
|
@files = ::Mongrel::DirHandler.new(options[:docroot], false)
|
57
62
|
@tick = Time.now
|
@@ -89,7 +94,7 @@ module Ap4r
|
|
89
94
|
def reload!
|
90
95
|
begin
|
91
96
|
#TODO not implemented 2007/04/09 by shino
|
92
|
-
raise "not yet implemented
|
97
|
+
raise "not yet implemented!"
|
93
98
|
end
|
94
99
|
end
|
95
100
|
|
@@ -86,8 +86,7 @@ module Ap4r::Mongrel
|
|
86
86
|
|
87
87
|
valid_dir? File.dirname(@log_file), "Path to log file not valid: #@log_file"
|
88
88
|
valid_dir? File.dirname(@pid_file), "Path to pid file not valid: #@pid_file"
|
89
|
-
|
90
|
-
#valid_dir? @docroot, "Path to docroot not valid: #@docroot"
|
89
|
+
valid_dir? @docroot, "Path to docroot not valid: #@docroot"
|
91
90
|
|
92
91
|
return @valid
|
93
92
|
end
|
data/lib/ap4r/multi_queue.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# Author:: Shunichi Shinohara
|
2
|
-
# Copyright:: Copyright (c)
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
5
|
module ReliableMsg
|
6
|
+
|
6
7
|
# The +MultiQueue+ is a kind of clients.
|
7
8
|
# This offers two extentions to <tt>ReliableMsg::Queue</tt>
|
8
9
|
# 1. specify multiple target queues, by as comma-separated queue names.
|
@@ -1,31 +1,84 @@
|
|
1
1
|
# Author:: Shunichi Shinohara
|
2
|
-
# Copyright:: Copyright (c)
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
|
-
require 'ap4r/message_store_ext'
|
6
|
-
require 'ap4r/multi_queue'
|
7
|
-
require 'ap4r/retention_history'
|
8
|
-
|
9
|
-
require 'soap/wsdlDriver'
|
10
|
-
require 'xmlrpc/client'
|
11
|
-
require 'uri'
|
12
|
-
require 'net/http'
|
13
|
-
|
14
5
|
require 'active_support'
|
15
6
|
require 'yaml'
|
16
7
|
require 'thread'
|
17
8
|
require 'pp'
|
18
9
|
|
19
10
|
require 'uuid'
|
11
|
+
require 'reliable-msg'
|
20
12
|
|
21
|
-
|
22
|
-
|
13
|
+
require 'ap4r/message_store_ext'
|
14
|
+
require 'ap4r/multi_queue'
|
15
|
+
require 'ap4r/retention_history'
|
16
|
+
require 'ap4r/dispatcher'
|
17
|
+
require 'ap4r/carrier'
|
18
|
+
|
19
|
+
module ReliableMsg #:nodoc:
|
20
|
+
|
21
|
+
# = Dynamic configuration with ERb
|
22
|
+
#
|
23
|
+
# Some times you would like to inject dynamic values into your configuration file.
|
24
|
+
# In these cases, you can mix ERb in with your YAML to code some logic, like:
|
25
|
+
#
|
26
|
+
# <% acl = [] %>
|
27
|
+
# <% for i in 1..100 %>
|
28
|
+
# <% acl << "192.168.0.#{i}" %>
|
29
|
+
# <% end %>
|
30
|
+
# acl: <%= acl.map{|ip| "allow #{ip}"}.join(' ')
|
31
|
+
#
|
32
|
+
class Config
|
23
33
|
|
34
|
+
alias :load_no_create_original :load_no_create
|
35
|
+
alias :load_or_create_original :load_or_create
|
36
|
+
|
37
|
+
#--
|
38
|
+
# TODO: should enhance YAML.load_documents instead of this method?, 2007/5/7 kato-k
|
39
|
+
def load_no_create
|
40
|
+
if File.exist?(@file)
|
41
|
+
@config= {}
|
42
|
+
File.open @file, "r" do |input|
|
43
|
+
YAML.load_documents(erb_render(input.read)) do |doc|
|
44
|
+
@config.merge! doc
|
45
|
+
end
|
46
|
+
end
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
#--
|
52
|
+
# TODO: should enhance YAML.load_documents instead of this method?, 2007/5/7 kato-k
|
53
|
+
def load_or_create
|
54
|
+
if File.exist?(@file)
|
55
|
+
@config= {}
|
56
|
+
File.open @file, "r" do |input|
|
57
|
+
YAML.load_documents(erb_render(input.read)) do |doc|
|
58
|
+
@config.merge! doc
|
59
|
+
end
|
60
|
+
end
|
61
|
+
@logger.info format(INFO_LOADED_CONFIG, @file)
|
62
|
+
else
|
63
|
+
@config = {
|
64
|
+
"store" => DEFAULT_STORE,
|
65
|
+
"drb" => DEFAULT_DRB
|
66
|
+
}
|
67
|
+
save
|
68
|
+
@logger.info format(INFO_CREATED_CONFIG, @file)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
def erb_render(configuration_content)
|
74
|
+
ERB.new(configuration_content).result
|
75
|
+
end
|
24
76
|
end
|
25
|
-
|
77
|
+
|
26
78
|
class QueueManager
|
27
|
-
|
28
|
-
#
|
79
|
+
|
80
|
+
# Gets a queue name which has the most stale message.
|
81
|
+
# +multi_queue+ specifies the target queue names to search.
|
29
82
|
def stale_queue multi_queue
|
30
83
|
@store.stale_queue multi_queue
|
31
84
|
end
|
@@ -37,7 +90,6 @@ module ReliableMsg
|
|
37
90
|
# Hooks original initialize method to add lifecyle listeners.
|
38
91
|
#--
|
39
92
|
# TODO: Make dispatchers and carriers lifecyle listeners, 2006/09/01 shino
|
40
|
-
# TODO: and separate them from QueueManager, 2006/09/01 shino
|
41
93
|
def initialize options = nil #:notnew:
|
42
94
|
initialize_original options
|
43
95
|
@global_lock ||= Mutex.new
|
@@ -51,14 +103,25 @@ module ReliableMsg
|
|
51
103
|
self.class.class_eval("attr_#{attr_mode} :#{iv_name}")
|
52
104
|
end
|
53
105
|
|
106
|
+
# Starts reliable-msg server and something around it.
|
107
|
+
#
|
108
|
+
# Order is:
|
109
|
+
# 1. Original reliable-msg server (message store and druby).
|
110
|
+
# 2. Dispatchers
|
111
|
+
# 3. Carriors (if exists)
|
112
|
+
# These are Reversed in +stop+.
|
54
113
|
def start
|
55
114
|
begin
|
56
115
|
@global_lock.synchronize do
|
57
116
|
return if @@active == self
|
58
|
-
@dispatch_targets = ''
|
59
117
|
start_original
|
60
|
-
|
61
|
-
|
118
|
+
|
119
|
+
@dispatchers = ::Ap4r::Dispatchers.new(self, @config.dispatchers, @logger)
|
120
|
+
@dispatchers.start
|
121
|
+
|
122
|
+
@carriors = ::Ap4r::Carriers.new(self, @config.carriers, @logger, @dispatchers)
|
123
|
+
@carriors.start
|
124
|
+
|
62
125
|
@lifecycle_listeners.each {|l| l.start }
|
63
126
|
end
|
64
127
|
rescue Exception => err
|
@@ -67,195 +130,18 @@ module ReliableMsg
|
|
67
130
|
end
|
68
131
|
end
|
69
132
|
|
133
|
+
# Stops reliable-msg server and something around it.
|
134
|
+
# See +start+ also.
|
70
135
|
def stop
|
71
136
|
@global_lock.synchronize do
|
72
137
|
return unless @@active == self
|
73
138
|
@lifecycle_listeners.each {|l| l.stop }
|
74
|
-
|
75
|
-
|
139
|
+
@carriors.stop
|
140
|
+
@dispatchers.stop
|
76
141
|
stop_original
|
77
142
|
end
|
78
143
|
end
|
79
144
|
|
80
|
-
def start_dispatchers
|
81
|
-
begin
|
82
|
-
return unless @config.dispatchers
|
83
|
-
@logger.info{ "about to start dispatchers with config #{@config.dispatchers.to_yaml}" }
|
84
|
-
@disps = ThreadGroup.new
|
85
|
-
@config.dispatchers.each{ |conf|
|
86
|
-
conf["threads"].to_i.times { |index|
|
87
|
-
Thread.fork(@disps, conf["targets"], index){|group, targets, index|
|
88
|
-
dispatch_loop(group, targets, index)
|
89
|
-
}
|
90
|
-
}
|
91
|
-
@dispatch_targets.concat(conf["targets"]).concat(';')
|
92
|
-
@logger.info{ "dispatch targets are : #{@dispatch_targets}" }
|
93
|
-
}
|
94
|
-
@logger.info "queue manager has forked dispatchers"
|
95
|
-
rescue Exception => err
|
96
|
-
@logger.warn{"Error in starting dipatchers #{err}"}
|
97
|
-
@logger.warn{err.backtrace.join("\n")}
|
98
|
-
raise err
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def dispatch_loop(group, targets, index)
|
103
|
-
group.add Thread.current
|
104
|
-
mq = MultiQueue.new targets
|
105
|
-
@logger.info{ "start dispatcher: targets= #{mq} (index #{index})" }
|
106
|
-
until Thread.current[:dying]
|
107
|
-
sleep 0.1
|
108
|
-
# @logger.debug{ "try dispatch #{mq} #{mq.name}" }
|
109
|
-
# TODO: needs timeout?, 2006/10/16 shino
|
110
|
-
begin
|
111
|
-
mq.get{|m|
|
112
|
-
@logger.debug{"dispatcher get message\n#{m.to_yaml}"} if m
|
113
|
-
response =
|
114
|
-
case m.headers[:dispatch_mode]
|
115
|
-
when :HTTP
|
116
|
-
dispatch_via_http(m)
|
117
|
-
when :XMLRPC
|
118
|
-
dispatch_via_xmlrpc(m)
|
119
|
-
when :SOAP
|
120
|
-
dispatch_via_soap(m)
|
121
|
-
else
|
122
|
-
raise "undefined dispatch mode #{m.headers[:mode]}"
|
123
|
-
end
|
124
|
-
@logger.debug{"dispatcher get response\n#{response.to_yaml}"}
|
125
|
-
}
|
126
|
-
rescue Exception => err
|
127
|
-
@logger.warn("dispatch err #{err.inspect}")
|
128
|
-
@logger.warn(err.backtrace.join("\n"))
|
129
|
-
end
|
130
|
-
end
|
131
|
-
@logger.info{"end dispatcher #{mq} (index #{index})"}
|
132
|
-
end
|
133
|
-
|
134
|
-
# Dispatch via a HTTP protocol
|
135
|
-
# Current implementation uses POST method, irrespectively options[:target_method]
|
136
|
-
#
|
137
|
-
# Determination of "success" is two fold
|
138
|
-
# * status code should be 200, other codes (including 201-2xx) are treated as error
|
139
|
-
# * when status code is 200, body should include a string "true"
|
140
|
-
def dispatch_via_http(message)
|
141
|
-
#TODO: Add some request headers e.g. User-Agent and Accept, 2006/10/12 shino
|
142
|
-
#TODO: Now support POST only, 2006/10/12 shino
|
143
|
-
response = Net::HTTP.post_form(URI.parse(message[:target_url]),
|
144
|
-
message.object)
|
145
|
-
@logger.debug{"response status [#{response.code} #{response.message}]"}
|
146
|
-
|
147
|
-
#TODO: make the difinition of success variable, 2006/10/13 shino
|
148
|
-
unless response.kind_of?(Net::HTTPOK)
|
149
|
-
error_message = "HTTP Response FAILURE, status [#{response.code} #{response.message}]"
|
150
|
-
@logger.error(error_message)
|
151
|
-
@logger.info{response.to_yaml}
|
152
|
-
#TODO: must create AP4R specific Exception class, 2006/10/12 shino
|
153
|
-
raise StandardError.new(error_message)
|
154
|
-
end
|
155
|
-
|
156
|
-
unless response.body =~ /true/
|
157
|
-
error_message = "HTTP Response FAILURE, status [#{response.code} #{response.message}], body [#{response.body}]"
|
158
|
-
#TODO: Refactor error logging, 2006/10/13 shino
|
159
|
-
@logger.error(error_message)
|
160
|
-
@logger.info{response.to_yaml}
|
161
|
-
#TODO: must create AP4R specific Exception class, 2006/10/12 shino
|
162
|
-
raise StandardError.new(error_message)
|
163
|
-
end
|
164
|
-
|
165
|
-
response
|
166
|
-
end
|
167
|
-
|
168
|
-
def dispatch_via_xmlrpc(message)
|
169
|
-
endpoint = message[:target_url]
|
170
|
-
client = XMLRPC::Client.new2(endpoint)
|
171
|
-
success, response = client.call2(message[:target_action], message.object)
|
172
|
-
raise response unless success
|
173
|
-
response
|
174
|
-
end
|
175
|
-
|
176
|
-
def dispatch_via_soap(message)
|
177
|
-
@logger.debug{message[:target_url]}
|
178
|
-
driver = SOAP::WSDLDriverFactory.new(message[:target_url]).create_rpc_driver
|
179
|
-
@logger.debug{driver}
|
180
|
-
driver.send(message[:target_action], message.object)
|
181
|
-
end
|
182
|
-
|
183
|
-
def stop_dispatchers
|
184
|
-
@logger.info{"stop_dispatchers #{@disps}"}
|
185
|
-
return unless @disps
|
186
|
-
@disps.list.each {|d| d[:dying] = true}
|
187
|
-
@disps.list.each {|d| d.join }
|
188
|
-
end
|
189
|
-
|
190
|
-
def start_carriers
|
191
|
-
conf = @config.carriers
|
192
|
-
return unless conf
|
193
|
-
|
194
|
-
@logger.info{ "ready to start carrires with config #{conf.to_yaml}" }
|
195
|
-
@carriers = ThreadGroup.new
|
196
|
-
conf.each { |remote|
|
197
|
-
remote["threads"].times { |index|
|
198
|
-
Thread.fork(@carriers, remote, index){|group, remote, index|
|
199
|
-
# TODO: refactor structure, 2006/10/06 shino
|
200
|
-
group.add Thread.current
|
201
|
-
@logger.info{ "starting a carrier (index #{index}) for the queue manager #{remote['source_uri']}" }
|
202
|
-
uri = remote['source_uri']
|
203
|
-
until Thread.current[:dying]
|
204
|
-
begin
|
205
|
-
sleep 0.1
|
206
|
-
#TODO check :dying flag here and break, 2006/09/01 shino
|
207
|
-
#TODO cache DRbObject if necessary, 2006/09/01 shino
|
208
|
-
remote_qm = DRb::DRbObject.new_with_uri(uri)
|
209
|
-
queue_name = remote_qm.stale_queue @dispatch_targets
|
210
|
-
next unless queue_name
|
211
|
-
|
212
|
-
@logger.debug{ "stale queue name : #{queue_name}" }
|
213
|
-
q = ReliableMsg::Queue.new queue_name, :drb_uri => uri
|
214
|
-
q.get { |m|
|
215
|
-
unless m
|
216
|
-
@logger.debug{ "carrier strikes at the air (T_T)" }
|
217
|
-
next
|
218
|
-
end
|
219
|
-
# @logger.debug{ "carrier gets a message\n#{m.to_yaml}" }
|
220
|
-
|
221
|
-
# TODO: decide the better one, and delete another, 2006/09/01 shino
|
222
|
-
# TODO: or switchable implementation in versions, 2006/10/16 shino
|
223
|
-
|
224
|
-
#version 1: use thread fork so queue manager use a different tx
|
225
|
-
# TODO probably should have a thread as an instance variable or in a thread local, 2006/09/01 shino
|
226
|
-
#Thread.fork(m) {|m|
|
227
|
-
# local_queue = ReliableMsg::Queue.new queue_name
|
228
|
-
# local_queue.put m.object
|
229
|
-
#}.join
|
230
|
-
|
231
|
-
#version 2: store tx and set nil, and resotre tx after putting a message
|
232
|
-
begin
|
233
|
-
tx = Thread.current[ReliableMsg::Client::THREAD_CURRENT_TX]
|
234
|
-
Thread.current[ReliableMsg::Client::THREAD_CURRENT_TX] = nil
|
235
|
-
# @logger.debug{ "before tx: #{tx}" }
|
236
|
-
ReliableMsg::Queue.new(queue_name).put(m.object)
|
237
|
-
ensure
|
238
|
-
Thread.current[ReliableMsg::Client::THREAD_CURRENT_TX] = tx
|
239
|
-
# @logger.debug{ "after tx: #{Thread.current[ReliableMsg::Client::THREAD_CURRENT_TX]}" }
|
240
|
-
end
|
241
|
-
}
|
242
|
-
rescue Exception => ex
|
243
|
-
@logger.warn "error in remote-get/local-put #{ex}\n#{ex.backtrace.join("\n\t")}\n"
|
244
|
-
end
|
245
|
-
end
|
246
|
-
@logger.info{"ends a carrier (index #{index}) for the queue manager #{remote['uri']}"}
|
247
|
-
}
|
248
|
-
}
|
249
|
-
}
|
250
|
-
@logger.info{"queue manager has forked all carriers"}
|
251
|
-
end
|
252
|
-
|
253
|
-
def stop_carriers
|
254
|
-
@logger.info{"stop_carriers #{@carriers}"}
|
255
|
-
return unless @carriers
|
256
|
-
@carriers.list.each{|d| d[:dying] = true}
|
257
|
-
@carriers.list.each{|d| d.join }
|
258
|
-
end
|
259
145
|
|
260
146
|
end
|
261
147
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# Author:: Shunichi Shinohara
|
2
|
-
# Copyright:: Copyright (c)
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
5
|
require 'drb/drb'
|
6
6
|
|
7
|
-
module ReliableMsg
|
7
|
+
module ReliableMsg #:nodoc:
|
8
8
|
class QueueManager
|
9
|
-
attr_reader :store, :transactions, :mutex, :config
|
9
|
+
attr_reader :store, :transactions, :mutex, :config, :dispatchers, :carriers
|
10
10
|
|
11
11
|
# Accepts ruby code as a string, evaluates it on +self+,
|
12
12
|
# and returns the result as a formatted string.
|
@@ -38,9 +38,16 @@ module ReliableMsg
|
|
38
38
|
end
|
39
39
|
alias e2i eval_to_inspect
|
40
40
|
|
41
|
+
# Checks queues are all "empty".
|
42
|
+
#
|
43
|
+
# "Empty" means no messages in transaction and
|
44
|
+
# all queues but <tt>$dlq</tt> are empty.
|
45
|
+
def no_active_message?
|
46
|
+
@transactions.size.zero? && @store.queues.all?{|(q, ms)| q == "$dlq" || ms.size.zero? }
|
47
|
+
end
|
41
48
|
end
|
42
49
|
|
43
|
-
module MessageStore
|
50
|
+
module MessageStore #:nodoc:
|
44
51
|
class Base
|
45
52
|
include DRbUndumped
|
46
53
|
attr_reader :mutex, :queues, :topics, :cache
|
@@ -50,9 +57,10 @@ module ReliableMsg
|
|
50
57
|
def activate
|
51
58
|
activate_original
|
52
59
|
@mutex.extend DRbUndumped
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
60
|
+
# TODO: queues/topics/cache should be DRbUndumped? 2007/06/06 by shino
|
61
|
+
# @queues.extend DRbUndumped
|
62
|
+
# @topics.extend DRbUndumped
|
63
|
+
# @cache.extend DRbUndumped
|
56
64
|
end
|
57
65
|
|
58
66
|
end
|