ap4r 0.3.6 → 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +2 -0
- data/Manifest.txt +5 -0
- data/Rakefile +1 -21
- data/config/queues_pgsql.cfg +7 -6
- data/fresh_rakefile +10 -0
- data/lib/ap4r/async_helper.rb +375 -0
- data/lib/ap4r/dispatcher.rb +2 -1
- data/lib/ap4r/message_store_ext.rb +1 -1
- data/lib/ap4r/mongrel.rb +83 -0
- data/lib/ap4r/mongrel_ap4r.rb +1 -0
- data/lib/ap4r/script/workspace_generator.rb +9 -2
- data/lib/ap4r/version.rb +1 -1
- data/lib/tasks/ap4r.rb +7 -0
- data/lib/tasks/databases.rake +37 -0
- data/script/mongrel_ap4r +3 -1
- data/spec/local/async_helper_queue_put_spec.rb +418 -0
- data/spec/local/message_builder_spec.rb +1 -1
- metadata +12 -12
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -11,7 +11,9 @@ config/queues_ar.cfg
|
|
11
11
|
config/queues_disk.cfg
|
12
12
|
config/queues_mysql.cfg
|
13
13
|
config/queues_pgsql.cfg
|
14
|
+
fresh_rakefile
|
14
15
|
lib/ap4r.rb
|
16
|
+
lib/ap4r/async_helper.rb
|
15
17
|
lib/ap4r/carrier.rb
|
16
18
|
lib/ap4r/db/migrate/001_reliable_msg_queue_and_topic.rb
|
17
19
|
lib/ap4r/dispatcher.rb
|
@@ -39,6 +41,8 @@ lib/ap4r/util/queue_client.rb
|
|
39
41
|
lib/ap4r/version.rb
|
40
42
|
lib/ap4r/xxx_create_table_for_saf.rb
|
41
43
|
lib/ap4r/xxx_create_table_for_saf_to_postgresql.rb
|
44
|
+
lib/tasks/ap4r.rb
|
45
|
+
lib/tasks/databases.rake
|
42
46
|
rails_plugin/ap4r/init.rb
|
43
47
|
rails_plugin/ap4r/lib/ap4r/queue_put_stub.rb
|
44
48
|
rails_plugin/ap4r/lib/ap4r/service_handler.rb
|
@@ -49,6 +53,7 @@ script/irm
|
|
49
53
|
script/mongrel_ap4r
|
50
54
|
script/start
|
51
55
|
script/stop
|
56
|
+
spec/local/async_helper_queue_put_spec.rb
|
52
57
|
spec/local/dispatcher_base_spec.rb
|
53
58
|
spec/local/message_builder_spec.rb
|
54
59
|
spec/local/send_message_handler_spec.rb
|
data/Rakefile
CHANGED
@@ -18,7 +18,7 @@ begin
|
|
18
18
|
p.email = %q{shinohara.shunichi@future.co.jp, kato.kiwamu@future.co.jp}
|
19
19
|
|
20
20
|
p.extra_deps << ['reliable-msg', '=1.1.0']
|
21
|
-
p.extra_deps << ['activesupport']
|
21
|
+
# p.extra_deps << ['activesupport']
|
22
22
|
p.extra_deps << ['mongrel']
|
23
23
|
p.extra_deps << ['rake']
|
24
24
|
p.extra_deps << ['hoe']
|
@@ -151,26 +151,6 @@ task :stats => "release:copy_plugin" do
|
|
151
151
|
).to_s
|
152
152
|
end
|
153
153
|
|
154
|
-
namespace :qdb do
|
155
|
-
desc "Make queue and topic tables through scripts in lib/ap4r/db/migrate."
|
156
|
-
task :migrate do
|
157
|
-
|
158
|
-
# Todo: configurable file name, 2007/10/01 kiwamu
|
159
|
-
ap4r_config_file = "config/queues_ar.cfg"
|
160
|
-
ap4r_config = YAML::load(ERB.new(IO.read(ap4r_config_file)).result)
|
161
|
-
database_config = ap4r_config["store"]
|
162
|
-
if "activerecord" == database_config["type"].downcase
|
163
|
-
database_config["adapter"] = database_config["adapter"].downcase
|
164
|
-
else
|
165
|
-
# Todo
|
166
|
-
end
|
167
|
-
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
168
|
-
ActiveRecord::Base.establish_connection(database_config)
|
169
|
-
|
170
|
-
ActiveRecord::Migrator.migrate("lib/ap4r/db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
154
|
todos_dirs = %w(lib rails_plugin spec)
|
175
155
|
|
176
156
|
desc "List TODO comments in #{todos_dirs.join(", ")} directories"
|
data/config/queues_pgsql.cfg
CHANGED
@@ -1,12 +1,13 @@
|
|
1
|
-
---
|
2
|
-
store:
|
1
|
+
---
|
2
|
+
store:
|
3
3
|
type: postgresql
|
4
|
-
|
4
|
+
host: localhost
|
5
|
+
port: 5432
|
5
6
|
database: ap4r
|
6
7
|
username: ap4r
|
7
8
|
password: ap4r
|
8
|
-
drb:
|
9
|
-
host:
|
9
|
+
drb:
|
10
|
+
host:
|
10
11
|
port: 6438
|
11
12
|
acl: allow 127.0.0.1 allow ::1 allow 10.0.0.0/8
|
12
13
|
dispatchers:
|
@@ -14,6 +15,6 @@ dispatchers:
|
|
14
15
|
targets: queue.*
|
15
16
|
threads: 1
|
16
17
|
#carriers:
|
17
|
-
# -
|
18
|
+
# -
|
18
19
|
# source_uri: druby://another.host.local:6438
|
19
20
|
# threads: 1
|
data/fresh_rakefile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
3
|
+
|
4
|
+
require 'rake'
|
5
|
+
require 'rake/testtask'
|
6
|
+
require 'rake/rdoctask'
|
7
|
+
|
8
|
+
require 'ap4r'
|
9
|
+
require 'tasks/ap4r'
|
10
|
+
|
@@ -0,0 +1,375 @@
|
|
1
|
+
# Author:: Shunichi Shinohara
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
|
+
# Licence:: MIT Licence
|
4
|
+
|
5
|
+
require 'reliable-msg'
|
6
|
+
require 'ap4r/stored_message'
|
7
|
+
require 'ap4r/message_builder'
|
8
|
+
|
9
|
+
module Ap4r
|
10
|
+
|
11
|
+
# This +AsyncHelper+ is included to +Ap4rClient+ and works the Rails plugin
|
12
|
+
# for asynchronous processing.
|
13
|
+
#
|
14
|
+
module AsyncHelper
|
15
|
+
|
16
|
+
module Base
|
17
|
+
Converters = {}
|
18
|
+
|
19
|
+
DRUBY_HOST = ENV['AP4R_DRUBY_HOST'] || 'localhost'
|
20
|
+
DRUBY_PORT = ENV['AP4R_DRUBY_PORT'] || '6438'
|
21
|
+
DRUBY_URI = "druby://#{DRUBY_HOST}:#{DRUBY_PORT}"
|
22
|
+
|
23
|
+
@@druby_uris = [DRUBY_URI]
|
24
|
+
@@druby_uri_options = { :rotate => false, :fail_over => false, :fail_reuse => false }
|
25
|
+
@@druby_uri_retry_count = 0
|
26
|
+
@@druby_uris_size = 1
|
27
|
+
|
28
|
+
@@default_dispatch_mode = :HTTP
|
29
|
+
@@default_rm_options = { :delivery => :once, :dispatch_mode => @@default_dispatch_mode }
|
30
|
+
@@default_queue_prefix = "queue."
|
31
|
+
|
32
|
+
mattr_accessor :default_dispatch_mode, :default_rm_options, :default_queue_prefix, :saf_delete_mode
|
33
|
+
|
34
|
+
def druby_uris(uris, options = {})
|
35
|
+
@@druby_uris = []
|
36
|
+
if uris.empty?
|
37
|
+
@@druby_uris << DRUBY_URI
|
38
|
+
else
|
39
|
+
@@druby_uris << uris
|
40
|
+
@@druby_uris.flatten!
|
41
|
+
end
|
42
|
+
@@druby_uri_options = @@druby_uri_options.merge(options)
|
43
|
+
@@druby_uris_size = @@druby_uris.size
|
44
|
+
@@druby_uri_retry_count = 0
|
45
|
+
end
|
46
|
+
module_function :druby_uris
|
47
|
+
|
48
|
+
# This method is aliased as ::Ap4r::Client#transaction
|
49
|
+
#
|
50
|
+
def transaction_with_saf(active_record_class = ::Ap4r::StoredMessage, *objects, &block)
|
51
|
+
|
52
|
+
Thread.current[:use_saf] = true
|
53
|
+
Thread.current[:stored_messages] = {}
|
54
|
+
|
55
|
+
# store
|
56
|
+
active_record_class ||= ::Ap4r::StoredMessage
|
57
|
+
active_record_class.transaction(*objects, &block)
|
58
|
+
|
59
|
+
# forward
|
60
|
+
forwarded_messages = {}
|
61
|
+
begin
|
62
|
+
|
63
|
+
# TODO: reconsider forwarding strategy, 2006/10/13 kato-k
|
64
|
+
# Once some error occured, such as disconnect reliable-msg or server crush,
|
65
|
+
# which is smart to keep to put a message or stop to do it?
|
66
|
+
# In the case of being many async messages, the former strategy is not so good.
|
67
|
+
#
|
68
|
+
# TODO: add delayed forward mode 2007/05/02 by shino
|
69
|
+
Thread.current[:stored_messages].each {|k,v|
|
70
|
+
__queue_put(v[:queue_name], v[:queue_message], v[:queue_headers])
|
71
|
+
forwarded_messages[k] = v
|
72
|
+
}
|
73
|
+
rescue Exception => err
|
74
|
+
# Don't raise any Exception. Application logic has already completed and messages are saved.
|
75
|
+
logger.warn("Failed to put a message into queue: #{err}")
|
76
|
+
end
|
77
|
+
|
78
|
+
begin
|
79
|
+
StoredMessage.transaction do
|
80
|
+
options = {:delete_mode => @@saf_delete_mode || :physical}
|
81
|
+
forwarded_messages.keys.each {|id|
|
82
|
+
::Ap4r::StoredMessage.destroy_if_exists(id, options)
|
83
|
+
}
|
84
|
+
end
|
85
|
+
rescue Exception => err
|
86
|
+
# Don't raise any Exception. Application logic has already completed and messages are saved.
|
87
|
+
logger.warn("Failed to put a message into queue: #{err}")
|
88
|
+
end
|
89
|
+
|
90
|
+
ensure
|
91
|
+
Thread.current[:use_saf] = false
|
92
|
+
Thread.current[:stored_messages] = nil
|
93
|
+
end
|
94
|
+
|
95
|
+
# This method is aliased as ::Ap4r::Client#async_to
|
96
|
+
#
|
97
|
+
def async_dispatch(url_options = {}, async_params = {}, rm_options = {}, &block)
|
98
|
+
|
99
|
+
if logger.debug?
|
100
|
+
logger.debug("url_options: ")
|
101
|
+
logger.debug(url_options.inspect)
|
102
|
+
logger.debug("async_params: ")
|
103
|
+
logger.debug(async_params.inspect)
|
104
|
+
logger.debug("rm_options: ")
|
105
|
+
logger.debug(rm_options.inspect)
|
106
|
+
end
|
107
|
+
|
108
|
+
rm_options = @@default_rm_options.merge(rm_options || {})
|
109
|
+
|
110
|
+
# Only async_params is not cloned. options and rm_options are cloned before now.
|
111
|
+
# This is a current contract between this class and converter classes.
|
112
|
+
converter = Converters[rm_options[:dispatch_mode]].new(url_options, async_params, rm_options, self)
|
113
|
+
# logger.debug("druby uri for queue-manager : #{@@druby_uris.first}")
|
114
|
+
|
115
|
+
queue_name = converter.queue_name
|
116
|
+
queue_message = converter.make_params
|
117
|
+
queue_headers = converter.make_rm_options
|
118
|
+
|
119
|
+
message_builder = ::Ap4r::MessageBuilder.new(queue_name, queue_message, queue_headers)
|
120
|
+
if block_given?
|
121
|
+
message_builder.instance_eval(&block)
|
122
|
+
end
|
123
|
+
queue_name = message_builder.queue_name
|
124
|
+
queue_headers = message_builder.message_headers
|
125
|
+
# TODO: proces flow of Converter and MessageBuilder should (probably) be reversed 2007/09/19 by shino
|
126
|
+
# This branching is ad-hoc fix
|
127
|
+
if queue_headers[:dispatch_mode] == :HTTP
|
128
|
+
queue_message = message_builder.format_message_body
|
129
|
+
else
|
130
|
+
queue_message = message_builder.message_body
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
if Thread.current[:use_saf]
|
135
|
+
stored_message = ::Ap4r::StoredMessage.store(queue_name, queue_message, queue_headers)
|
136
|
+
|
137
|
+
Thread.current[:stored_messages].store(
|
138
|
+
stored_message.id,
|
139
|
+
{
|
140
|
+
:queue_message => queue_message,
|
141
|
+
:queue_name => queue_name,
|
142
|
+
:queue_headers => queue_headers
|
143
|
+
} )
|
144
|
+
return stored_message.id
|
145
|
+
end
|
146
|
+
|
147
|
+
__queue_put(queue_name, queue_message, queue_headers)
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
def __queue_put(queue_name, queue_message, queue_headers)
|
152
|
+
# TODO: can use a Queue instance repeatedly? 2007/05/02 by shino
|
153
|
+
begin
|
154
|
+
druby_uri = @@druby_uris.first
|
155
|
+
logger.debug "Trying to connect to #{druby_uri} (druby uri list : #{@@druby_uris.join(", ")})."
|
156
|
+
|
157
|
+
q = ReliableMsg::Queue.new(queue_name, :drb_uri => druby_uri)
|
158
|
+
q.put(queue_message, queue_headers)
|
159
|
+
|
160
|
+
logger.debug "#{druby_uri} was connected and message was enqueued successfully."
|
161
|
+
@@druby_uri_retry_count = 0
|
162
|
+
__rotate_druby_uri if @@druby_uri_options[:rotate]
|
163
|
+
rescue DRb::DRbConnError => err
|
164
|
+
raise err unless @@druby_uri_options[:fail_over]
|
165
|
+
logger.debug "#{druby_uri} was not connected."
|
166
|
+
|
167
|
+
unconnected_uri = @@druby_uris.shift
|
168
|
+
raise "No more active druby uri." if @@druby_uris.empty?
|
169
|
+
|
170
|
+
@@druby_uris << unconnected_uri if @@druby_uri_options[:fail_reuse]
|
171
|
+
@@druby_uri_retry_count += 1
|
172
|
+
|
173
|
+
if @@druby_uri_retry_count >= @@druby_uris_size
|
174
|
+
@@druby_uri_retry_count = 0
|
175
|
+
logger.debug "All registered druby uri was not connected."
|
176
|
+
raise err
|
177
|
+
end
|
178
|
+
|
179
|
+
__queue_put(queue_name, queue_message, queue_headers)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def __rotate_druby_uri()
|
184
|
+
druby_uri = @@druby_uris.shift
|
185
|
+
@@druby_uris << druby_uri
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
module Converters #:nodoc:
|
191
|
+
|
192
|
+
# A base class for converter classes.
|
193
|
+
# Responsibilities of subclasses are as folows
|
194
|
+
# * by +make_params+, convert async_params to appropriate object
|
195
|
+
# * by +make_rm_options+, make appropriate +Hash+ passed by <tt>ReliableMsg::Queue#put</tt>
|
196
|
+
class Base
|
197
|
+
|
198
|
+
# Difine a constant +DISPATCH_MODE+ to value 'mode_symbol' and
|
199
|
+
# add self to a Converters list.
|
200
|
+
def self.dispatch_mode(mode_symbol)
|
201
|
+
self.const_set(:DISPATCH_MODE, mode_symbol)
|
202
|
+
::Ap4r::AsyncHelper::Base::Converters[mode_symbol] = self
|
203
|
+
end
|
204
|
+
|
205
|
+
def initialize(url_options, async_params, rm_options, url_for_handler)
|
206
|
+
@url_options = url_options
|
207
|
+
@async_params = async_params
|
208
|
+
@rm_options = rm_options
|
209
|
+
@url_for_handler = url_for_handler
|
210
|
+
end
|
211
|
+
|
212
|
+
# Returns a queue name to which a message will be queued.
|
213
|
+
# Should be implemented by subclasses.
|
214
|
+
def queue_name
|
215
|
+
raise 'must be implemented in subclasses'
|
216
|
+
end
|
217
|
+
|
218
|
+
# Returns a object which passed to <tt>ReliableMsg::Queue.put(message, headers)</tt>'s
|
219
|
+
# first argument +message+.
|
220
|
+
# Should be implemented by subclasses.
|
221
|
+
def make_params
|
222
|
+
raise 'must be implemented in subclasses'
|
223
|
+
end
|
224
|
+
|
225
|
+
# Returns a object which passed to <tt>ReliableMsg::Queue.put(message, headers)</tt>'s
|
226
|
+
# second argument +headers+.
|
227
|
+
# Should be implemented by subclasses.
|
228
|
+
def make_rm_options
|
229
|
+
raise 'must be implemented in subclasses'
|
230
|
+
end
|
231
|
+
|
232
|
+
private
|
233
|
+
# helper method for <tt>ActionController#url_for</tt>
|
234
|
+
def url_for(url_for_options, *parameter_for_method_reference)
|
235
|
+
return url_for_options if url_for_options.kind_of?(String)
|
236
|
+
@url_for_handler.url_for(url_for_options, *parameter_for_method_reference)
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
class ToRailsBase < Base
|
242
|
+
def initialize(url_options, async_params, rm_options, url_for_handler)
|
243
|
+
super
|
244
|
+
|
245
|
+
@url_options ||= {}
|
246
|
+
@url_options[:controller] ||= @url_for_handler.controller_path.gsub("/", ".")
|
247
|
+
@url_options[:url] ||= {:controller => url_options[:controller], :action => url_options[:action]}
|
248
|
+
@url_options[:url][:controller] ||= url_options[:controller] if url_options[:url].kind_of?(Hash)
|
249
|
+
end
|
250
|
+
|
251
|
+
def queue_name
|
252
|
+
queue_name = @rm_options[:queue]
|
253
|
+
return queue_name if queue_name
|
254
|
+
|
255
|
+
queue_prefix = ::Ap4r::AsyncHelper::Base.default_queue_prefix
|
256
|
+
queue_prefix = queue_prefix.chomp(".")
|
257
|
+
url = @url_options[:url]
|
258
|
+
if url.kind_of?(Hash)
|
259
|
+
@rm_options[:queue] ||=
|
260
|
+
[queue_prefix, url[:controller].to_s, url[:action].to_s].join(".")
|
261
|
+
else
|
262
|
+
@rm_options[:queue] ||=
|
263
|
+
"#{queue_prefix}.#{URI.parse(url).path.gsub("/", ".")}"
|
264
|
+
end
|
265
|
+
@rm_options[:queue]
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
class Http < ToRailsBase
|
270
|
+
dispatch_mode :HTTP
|
271
|
+
|
272
|
+
def make_params
|
273
|
+
@async_params
|
274
|
+
end
|
275
|
+
|
276
|
+
def make_rm_options
|
277
|
+
@rm_options[:target_url] ||= url_for(@url_options[:url])
|
278
|
+
@rm_options[:target_method] ||= 'POST'
|
279
|
+
#TODO: make option key to specify HTTP headers, 2006/10/16 shino
|
280
|
+
@rm_options
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
class WebService < ToRailsBase
|
285
|
+
def make_params
|
286
|
+
message_obj = {}
|
287
|
+
@async_params.each_pair{|k,v| message_obj[k.to_sym]=v}
|
288
|
+
message_obj
|
289
|
+
end
|
290
|
+
|
291
|
+
def make_rm_options
|
292
|
+
@rm_options[:target_url] ||= target_url_name
|
293
|
+
@rm_options[:target_action] ||= action_api_name
|
294
|
+
@rm_options
|
295
|
+
end
|
296
|
+
|
297
|
+
def action_api_name
|
298
|
+
action_method_name = @url_options[:url][:action]
|
299
|
+
action_method_name.camelcase
|
300
|
+
end
|
301
|
+
|
302
|
+
def options_without_action
|
303
|
+
@url_options[:url].reject{ |k,v| k == :action }
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
307
|
+
|
308
|
+
class XmlRpc < WebService
|
309
|
+
dispatch_mode :XMLRPC
|
310
|
+
|
311
|
+
def target_url_name
|
312
|
+
url_for(options_without_action) + rails_api_url_suffix
|
313
|
+
end
|
314
|
+
|
315
|
+
private
|
316
|
+
def rails_api_url_suffix
|
317
|
+
'/api'
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
class SOAP < WebService
|
322
|
+
dispatch_mode :SOAP
|
323
|
+
|
324
|
+
def target_url_name
|
325
|
+
url_for(options_without_action) + rails_wsdl_url_suffix
|
326
|
+
end
|
327
|
+
|
328
|
+
private
|
329
|
+
def rails_wsdl_url_suffix
|
330
|
+
'/service.wsdl'
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
class Druby < Base
|
335
|
+
OPTION_KEY = :receiver
|
336
|
+
dispatch_mode :druby
|
337
|
+
|
338
|
+
@@default_url = "druby://localhost:9999"
|
339
|
+
cattr_accessor :default_url
|
340
|
+
|
341
|
+
def initialize(url_options, async_params, rm_options, url_for_handler)
|
342
|
+
super
|
343
|
+
@url_options[:url] ||= @@default_url
|
344
|
+
end
|
345
|
+
|
346
|
+
def queue_name
|
347
|
+
queue_name = @rm_options[:queue]
|
348
|
+
return queue_name if queue_name
|
349
|
+
|
350
|
+
@rm_options[:queue] =
|
351
|
+
[AsyncHelper::Base.default_queue_prefix.chomp("."),
|
352
|
+
@url_options[OPTION_KEY].to_s || "druby",
|
353
|
+
@url_options[:message].to_s].join(".")
|
354
|
+
@rm_options[:queue]
|
355
|
+
end
|
356
|
+
|
357
|
+
def make_params
|
358
|
+
@async_params
|
359
|
+
end
|
360
|
+
|
361
|
+
def make_rm_options
|
362
|
+
@rm_options[:target_url] ||=
|
363
|
+
if @url_options[OPTION_KEY]
|
364
|
+
"#{@url_options[:url]}?#{@url_options[OPTION_KEY]}"
|
365
|
+
else
|
366
|
+
@url_options[:url]
|
367
|
+
end
|
368
|
+
@rm_options[:target_method] = @url_options[:message]
|
369
|
+
@rm_options
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|
data/lib/ap4r/dispatcher.rb
CHANGED
@@ -497,7 +497,7 @@ if Object.const_defined? :PostgresPR
|
|
497
497
|
maybe_result = original_query(q, &block)
|
498
498
|
puts "PostgresPR: query called by #{q}" if $DEBUG
|
499
499
|
puts "PostgresPR::Connenction#query returns #{maybe_result}(class: #{maybe_result.class})." if $DEBUG
|
500
|
-
return maybe_result
|
500
|
+
return maybe_result unless block && maybe_result.kind_of?(PostgresPR::Connection::Result)
|
501
501
|
begin
|
502
502
|
puts "PostgresPR extention: about to yield result." if $DEBUG
|
503
503
|
block.call(maybe_result.rows)
|
data/lib/ap4r/mongrel.rb
CHANGED
@@ -291,5 +291,88 @@ module Ap4r
|
|
291
291
|
|
292
292
|
end
|
293
293
|
|
294
|
+
# This class is an experimental implementation of monitoring API by HTTP.
|
295
|
+
# It's possible to get the number of message in an arbitrary queue and
|
296
|
+
# the number of (alive/dead) thread of dispatchers.
|
297
|
+
#
|
298
|
+
# === Rrequest example ===
|
299
|
+
# GET /mointoring/queues/queue.test HTTP/1.1
|
300
|
+
# GET /mointoring/queues/all HTTP/1.1
|
301
|
+
# GET /mointoring/queues/dlq HTTP/1.1
|
302
|
+
#
|
303
|
+
# GET /mointoring/dispatchers/alive_threads HTTP/1.1
|
304
|
+
# GET /mointoring/dispatchers/dead_threads HTTP/1.1
|
305
|
+
#
|
306
|
+
class Ap4rMonitoringHandler < ::Mongrel::HttpHandler
|
307
|
+
|
308
|
+
def initialize(options)
|
309
|
+
@tick = Time.now
|
310
|
+
|
311
|
+
dlq = ReliableMsg::Queue.new "$dlq"
|
312
|
+
@qm = dlq.send :qm
|
313
|
+
end
|
314
|
+
|
315
|
+
def process(request, response)
|
316
|
+
if response.socket.closed?
|
317
|
+
return
|
318
|
+
end
|
319
|
+
|
320
|
+
target = request.params[::Mongrel::Const::PATH_INFO][1..-1]
|
321
|
+
|
322
|
+
if "GET".include? request.params[::Mongrel::Const::REQUEST_METHOD]
|
323
|
+
begin
|
324
|
+
# TODO: consider URL for each target, 2008/02/28 by kiwamu
|
325
|
+
result = case target
|
326
|
+
when /^queues\/*(\S*)/
|
327
|
+
case queue_name = $1
|
328
|
+
when ""
|
329
|
+
@qm.store.queues.keys.join(" ")
|
330
|
+
when "dlq"
|
331
|
+
@qm.store.queues["$dlq"].size
|
332
|
+
when "all"
|
333
|
+
@qm.store.queues.map{|k,v| v.size}.sum
|
334
|
+
else
|
335
|
+
@qm.store.queues[queue_name].size
|
336
|
+
end
|
337
|
+
when /^dispatchers\/*(\S*)/
|
338
|
+
case $1
|
339
|
+
when "alive_threads"
|
340
|
+
@qm.dispatchers.group.list.size
|
341
|
+
when "dead_threads"
|
342
|
+
diff = @qm.dispatchers.config.map{|d| d["threads"]}.sum - @qm.dispatchers.group.list.size
|
343
|
+
diff > 0 ? diff : 0
|
344
|
+
else
|
345
|
+
raise
|
346
|
+
end
|
347
|
+
else
|
348
|
+
raise
|
349
|
+
end
|
350
|
+
|
351
|
+
response.start(200) do |head, out|
|
352
|
+
head['Content-Type'] = 'text/plain'
|
353
|
+
out.write result
|
354
|
+
end
|
355
|
+
rescue
|
356
|
+
response.start(500) do |head, out|
|
357
|
+
head['Content-Type'] = 'text/plain'
|
358
|
+
out.write "Failed to monitor #{target}"
|
359
|
+
end
|
360
|
+
end
|
361
|
+
else
|
362
|
+
raise "HTTP method is not GET..."
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
# Does the internal reload for Rails. It might work for most cases, but
|
367
|
+
# sometimes you get exceptions. In that case just do a real restart.
|
368
|
+
def reload!
|
369
|
+
begin
|
370
|
+
#TODO not implemented 2007/04/09 by shino
|
371
|
+
raise "not yet implemented!"
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
end
|
376
|
+
|
294
377
|
end
|
295
378
|
end
|
data/lib/ap4r/mongrel_ap4r.rb
CHANGED
@@ -118,6 +118,7 @@ module Ap4r::Mongrel
|
|
118
118
|
uri "/", :handler => ::Ap4r::Mongrel::Ap4rHandler.new(defaults)
|
119
119
|
uri "/queues", :handler => ::Ap4r::Mongrel::Ap4rSendMessageHandler.new(defaults)
|
120
120
|
uri "/subscribes", :handler => ::Ap4r::Mongrel::Ap4rSubscribeMessageHandler.new(defaults)
|
121
|
+
uri "/monitoring", :handler => ::Ap4r::Mongrel::Ap4rMonitoringHandler.new(defaults)
|
121
122
|
end
|
122
123
|
setup_signals(settings)
|
123
124
|
end
|
@@ -9,11 +9,11 @@ module Ap4r
|
|
9
9
|
module Script
|
10
10
|
class WorkspaceGenerator < Base
|
11
11
|
AP4R_Directories = %w(config log public script tmp)
|
12
|
-
|
12
|
+
|
13
13
|
def run argv, options
|
14
14
|
OptionParser.new {|opt|
|
15
15
|
opt.on('-m'){
|
16
|
-
# merge to rails project but not implemented yet...
|
16
|
+
# merge to rails project but not implemented yet...
|
17
17
|
}
|
18
18
|
|
19
19
|
opt.parse!(argv)
|
@@ -38,6 +38,8 @@ module Ap4r
|
|
38
38
|
File.join(root_dir, recursive_copy_dir))
|
39
39
|
}
|
40
40
|
|
41
|
+
copy_file(File.join(ap4r_base, "fresh_rakefile"), File.join(root_dir, "Rakefile"))
|
42
|
+
|
41
43
|
logger.info{"\n[#{root_dir}] has successfully set up!\n"}
|
42
44
|
|
43
45
|
end
|
@@ -58,6 +60,11 @@ module Ap4r
|
|
58
60
|
}
|
59
61
|
end
|
60
62
|
|
63
|
+
def copy_file(src, dest)
|
64
|
+
FileUtils.cp(src, dest)
|
65
|
+
logger.info{"copy file from #{File.expand_path(src)} to #{dest} ..."}
|
66
|
+
end
|
67
|
+
|
61
68
|
end
|
62
69
|
end
|
63
70
|
end
|
data/lib/ap4r/version.rb
CHANGED
data/lib/tasks/ap4r.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'erb'
|
3
|
+
require 'find'
|
4
|
+
require 'active_record'
|
5
|
+
require File.join(File.dirname(__FILE__), '/../ap4r/version')
|
6
|
+
|
7
|
+
namespace :qdb do
|
8
|
+
desc "Make queue and topic tables through scripts in lib/ap4r/db/migrate."
|
9
|
+
task :migrate do
|
10
|
+
|
11
|
+
# Todo: configurable file name, 2007/10/01 kiwamu
|
12
|
+
ap4r_config_file = "config/queues_ar.cfg"
|
13
|
+
ap4r_config = YAML::load(ERB.new(IO.read(ap4r_config_file)).result)
|
14
|
+
database_config = ap4r_config["store"]
|
15
|
+
if "activerecord" == database_config["type"].downcase
|
16
|
+
database_config["adapter"] = database_config["adapter"].downcase
|
17
|
+
else
|
18
|
+
# Todo
|
19
|
+
end
|
20
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
21
|
+
ActiveRecord::Base.establish_connection(database_config)
|
22
|
+
|
23
|
+
ActiveRecord::Migrator.migrate("lib/ap4r/db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
namespace :db do
|
29
|
+
desc "Create table for persistent message."
|
30
|
+
task :create do
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
data/script/mongrel_ap4r
CHANGED
@@ -0,0 +1,418 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "../spec_helper")
|
2
|
+
|
3
|
+
require "reliable-msg"
|
4
|
+
require "ap4r/async_helper"
|
5
|
+
|
6
|
+
module Ap4r::AsyncHelper::Base
|
7
|
+
module_function :__queue_put
|
8
|
+
end
|
9
|
+
|
10
|
+
class Target
|
11
|
+
include Ap4r::AsyncHelper::Base
|
12
|
+
def initialize
|
13
|
+
@@logger = Logger.new(STDOUT)
|
14
|
+
@@logger.level = Logger::INFO
|
15
|
+
end
|
16
|
+
|
17
|
+
def queue_put
|
18
|
+
__queue_put("", { }, { })
|
19
|
+
end
|
20
|
+
|
21
|
+
require "active_support"
|
22
|
+
cattr_accessor :logger, :druby_uris, :druby_uri_retry_count
|
23
|
+
end
|
24
|
+
|
25
|
+
# mock
|
26
|
+
class ReliableMsg::Queue
|
27
|
+
def initialize(queue_name, options = { })
|
28
|
+
@druby_uri = options[:drb_uri]
|
29
|
+
end
|
30
|
+
|
31
|
+
def put(queue_message, queue_headers)
|
32
|
+
case @@ap4r_servers_status[@druby_uri]
|
33
|
+
when :active then "cd6f82d0-e9f1-012b-6ff8-0016cb9ad524" # uuid
|
34
|
+
when :inactive then raise ::DRb::DRbConnError
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
require "active_support"
|
39
|
+
cattr_accessor :ap4r_servers_status
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
describe Ap4r::AsyncHelper::Base, "no configuration and active server" do
|
44
|
+
|
45
|
+
before(:each) do
|
46
|
+
# status
|
47
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
48
|
+
"druby://localhost:6438" => :active
|
49
|
+
}
|
50
|
+
@target = Target.new
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should have default druby uri" do
|
54
|
+
@target.druby_uris.size.should == 1
|
55
|
+
@target.druby_uris.first.should == "druby://localhost:6438"
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should be not error" do
|
59
|
+
proc{ @target.queue_put }.should_not raise_error
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
describe Ap4r::AsyncHelper::Base, "no configuration and inactive server" do
|
65
|
+
|
66
|
+
before(:each) do
|
67
|
+
# status
|
68
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
69
|
+
"druby://localhost:6438" => :inactive
|
70
|
+
}
|
71
|
+
@target = Target.new
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should be not error" do
|
75
|
+
proc{ @target.queue_put }.should raise_error(::DRb::DRbConnError)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
describe Ap4r::AsyncHelper::Base, "multiple URIs with default options and active server" do
|
81
|
+
|
82
|
+
before(:each) do
|
83
|
+
# configuration
|
84
|
+
@uris = %w(6438 6439 6440).map {|port| "druby://localhost:#{port}"}
|
85
|
+
::Ap4r::AsyncHelper::Base.druby_uris(@uris)
|
86
|
+
|
87
|
+
# status
|
88
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
89
|
+
"druby://localhost:6438" => :active,
|
90
|
+
"druby://localhost:6439" => :active,
|
91
|
+
"druby://localhost:6440" => :active
|
92
|
+
}
|
93
|
+
|
94
|
+
@target = Target.new
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should have configured URIs list druby uri" do
|
98
|
+
@target.druby_uris.size.should == @uris.size
|
99
|
+
@target.druby_uris.should == @uris
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should be not error" do
|
103
|
+
proc{ @target.queue_put }.should_not raise_error
|
104
|
+
@target.druby_uris.first.should == @uris.first
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
describe Ap4r::AsyncHelper::Base, "multiple URIs with default options and inactive server" do
|
110
|
+
|
111
|
+
before(:each) do
|
112
|
+
# configuration
|
113
|
+
@uris = %w(6438 6439 6440).map {|port| "druby://localhost:#{port}"}
|
114
|
+
::Ap4r::AsyncHelper::Base.druby_uris(@uris)
|
115
|
+
|
116
|
+
# status
|
117
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
118
|
+
"druby://localhost:6438" => :inactive,
|
119
|
+
"druby://localhost:6439" => :active,
|
120
|
+
"druby://localhost:6440" => :active
|
121
|
+
}
|
122
|
+
|
123
|
+
@target = Target.new
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should be error (should not fail over)" do
|
127
|
+
@target.druby_uris.first.should == @uris.first
|
128
|
+
proc{ @target.queue_put }.should raise_error(::DRb::DRbConnError)
|
129
|
+
@target.druby_uris.first.should == @uris.first
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
describe Ap4r::AsyncHelper::Base, "multiple URIs with rotate option and active server" do
|
135
|
+
|
136
|
+
before(:each) do
|
137
|
+
# configuration
|
138
|
+
@uris = %w(6438 6439 6440).map {|port| "druby://localhost:#{port}"}
|
139
|
+
::Ap4r::AsyncHelper::Base.druby_uris(@uris, :rotate => true, :fail_over => false, :fail_reuse => false)
|
140
|
+
|
141
|
+
# status
|
142
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
143
|
+
"druby://localhost:6438" => :active,
|
144
|
+
"druby://localhost:6439" => :active,
|
145
|
+
"druby://localhost:6440" => :active
|
146
|
+
}
|
147
|
+
|
148
|
+
@target = Target.new
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should rotate servers each connection" do
|
152
|
+
@target.druby_uris.first.should == @uris[0]
|
153
|
+
proc{ @target.queue_put }.should_not raise_error
|
154
|
+
|
155
|
+
@target.druby_uris.first.should == @uris[1]
|
156
|
+
proc{ @target.queue_put }.should_not raise_error
|
157
|
+
|
158
|
+
@target.druby_uris.first.should == @uris[2]
|
159
|
+
proc{ @target.queue_put }.should_not raise_error
|
160
|
+
|
161
|
+
@target.druby_uris.first.should == @uris[0]
|
162
|
+
proc{ @target.queue_put }.should_not raise_error
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should have the same URIs list after connections" do
|
166
|
+
2.times{ @target.queue_put }
|
167
|
+
@target.druby_uris.size.should == 3
|
168
|
+
(@target.druby_uris - @uris).should == []
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
describe Ap4r::AsyncHelper::Base, "multiple URIs with rotate option and inactive 2nd server" do
|
174
|
+
|
175
|
+
before(:each) do
|
176
|
+
# configuration
|
177
|
+
@uris = %w(6438 6439 6440).map {|port| "druby://localhost:#{port}"}
|
178
|
+
::Ap4r::AsyncHelper::Base.druby_uris(@uris, :rotate => true, :fail_over => false, :fail_reuse => false)
|
179
|
+
|
180
|
+
# status
|
181
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
182
|
+
"druby://localhost:6438" => :active,
|
183
|
+
"druby://localhost:6439" => :inactive,
|
184
|
+
"druby://localhost:6440" => :active
|
185
|
+
}
|
186
|
+
|
187
|
+
@target = Target.new
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should be error on the 2nd connection" do
|
191
|
+
@target.druby_uris.first.should == @uris[0]
|
192
|
+
proc{ @target.queue_put }.should_not raise_error
|
193
|
+
|
194
|
+
@target.druby_uris.first.should == @uris[1]
|
195
|
+
proc{ @target.queue_put }.should raise_error(::DRb::DRbConnError)
|
196
|
+
|
197
|
+
@target.druby_uris.first.should == @uris[1]
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should be always error once error occured" do
|
201
|
+
@target.druby_uris.first.should == @uris[0]
|
202
|
+
proc{ @target.queue_put }.should_not raise_error
|
203
|
+
|
204
|
+
@target.druby_uris.first.should == @uris[1]
|
205
|
+
proc{ @target.queue_put }.should raise_error(::DRb::DRbConnError)
|
206
|
+
|
207
|
+
@target.druby_uris.first.should == @uris[1]
|
208
|
+
proc{ @target.queue_put }.should raise_error(::DRb::DRbConnError)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
|
213
|
+
describe Ap4r::AsyncHelper::Base, "multiple URIs with failover option and inactive 1st server" do
|
214
|
+
|
215
|
+
before(:each) do
|
216
|
+
# configuration
|
217
|
+
@uris = %w(6438 6439 6440).map {|port| "druby://localhost:#{port}"}
|
218
|
+
::Ap4r::AsyncHelper::Base.druby_uris(@uris, :rotate => false, :fail_over => true, :fail_reuse => false)
|
219
|
+
|
220
|
+
# status
|
221
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
222
|
+
"druby://localhost:6438" => :inactive,
|
223
|
+
"druby://localhost:6439" => :active,
|
224
|
+
"druby://localhost:6440" => :active
|
225
|
+
}
|
226
|
+
|
227
|
+
@target = Target.new
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should fail over to 2nd server" do
|
231
|
+
@target.druby_uris.first.should == @uris[0]
|
232
|
+
proc{ @target.queue_put }.should_not raise_error
|
233
|
+
|
234
|
+
@target.druby_uris.first.should == @uris[1]
|
235
|
+
proc{ @target.queue_put }.should_not raise_error
|
236
|
+
|
237
|
+
@target.druby_uris.first.should == @uris[1]
|
238
|
+
@target.druby_uris.size.should == 2
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
|
243
|
+
describe Ap4r::AsyncHelper::Base, "multiple URIs with failover option and inactive 1st & 2nd servers" do
|
244
|
+
|
245
|
+
before(:each) do
|
246
|
+
# configuration
|
247
|
+
@uris = %w(6438 6439 6440).map {|port| "druby://localhost:#{port}"}
|
248
|
+
::Ap4r::AsyncHelper::Base.druby_uris(@uris, :rotate => false, :fail_over => true, :fail_reuse => false)
|
249
|
+
|
250
|
+
# status
|
251
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
252
|
+
"druby://localhost:6438" => :inactive,
|
253
|
+
"druby://localhost:6439" => :inactive,
|
254
|
+
"druby://localhost:6440" => :active
|
255
|
+
}
|
256
|
+
|
257
|
+
@target = Target.new
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should fail over to 3rd server" do
|
261
|
+
@target.druby_uris.first.should == @uris[0]
|
262
|
+
proc{ @target.queue_put }.should_not raise_error
|
263
|
+
|
264
|
+
@target.druby_uris.first.should == @uris[2]
|
265
|
+
proc{ @target.queue_put }.should_not raise_error
|
266
|
+
|
267
|
+
@target.druby_uris.first.should == @uris[2]
|
268
|
+
@target.druby_uris.size.should == 1
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
describe Ap4r::AsyncHelper::Base, "multiple URIs with failover option and all inactive servers" do
|
274
|
+
|
275
|
+
before(:each) do
|
276
|
+
# configuration
|
277
|
+
@uris = %w(6438 6439 6440).map {|port| "druby://localhost:#{port}"}
|
278
|
+
::Ap4r::AsyncHelper::Base.druby_uris(@uris, :rotate => false, :fail_over => true, :fail_reuse => false)
|
279
|
+
|
280
|
+
# status
|
281
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
282
|
+
"druby://localhost:6438" => :inactive,
|
283
|
+
"druby://localhost:6439" => :inactive,
|
284
|
+
"druby://localhost:6440" => :inactive
|
285
|
+
}
|
286
|
+
|
287
|
+
@target = Target.new
|
288
|
+
end
|
289
|
+
|
290
|
+
it "should be error" do
|
291
|
+
@target.druby_uris.first.should == @uris[0]
|
292
|
+
proc{ @target.queue_put }.should raise_error(::RuntimeError, "No more active druby uri.")
|
293
|
+
|
294
|
+
@target.druby_uris.size.should == 0
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
describe Ap4r::AsyncHelper::Base, "multiple URIs with fail_reuse option and inactive 1st server" do
|
300
|
+
|
301
|
+
before(:each) do
|
302
|
+
# configuration
|
303
|
+
@uris = %w(6438 6439 6440).map {|port| "druby://localhost:#{port}"}
|
304
|
+
::Ap4r::AsyncHelper::Base.druby_uris(@uris, :rotate => false, :fail_over => true, :fail_reuse => true)
|
305
|
+
|
306
|
+
# status
|
307
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
308
|
+
"druby://localhost:6438" => :inactive,
|
309
|
+
"druby://localhost:6439" => :active,
|
310
|
+
"druby://localhost:6440" => :active
|
311
|
+
}
|
312
|
+
|
313
|
+
@target = Target.new
|
314
|
+
end
|
315
|
+
|
316
|
+
it "should have the same URIs list after fail over" do
|
317
|
+
@target.druby_uri_retry_count.should == 0
|
318
|
+
@target.druby_uris.first.should == @uris[0]
|
319
|
+
proc{ @target.queue_put }.should_not raise_error
|
320
|
+
@target.druby_uri_retry_count.should == 0
|
321
|
+
@target.druby_uris.first.should == @uris[1]
|
322
|
+
|
323
|
+
@target.druby_uris.size.should == @uris.size
|
324
|
+
(@target.druby_uris - @uris).should == []
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
|
329
|
+
describe Ap4r::AsyncHelper::Base, "multiple URIs with fail_reuse option and all inactive servers" do
|
330
|
+
|
331
|
+
before(:each) do
|
332
|
+
# configuration
|
333
|
+
@uris = %w(6438 6439 6440).map {|port| "druby://localhost:#{port}"}
|
334
|
+
::Ap4r::AsyncHelper::Base.druby_uris(@uris, :rotate => false, :fail_over => true, :fail_reuse => true)
|
335
|
+
|
336
|
+
# status
|
337
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
338
|
+
"druby://localhost:6438" => :inactive,
|
339
|
+
"druby://localhost:6439" => :inactive,
|
340
|
+
"druby://localhost:6440" => :inactive
|
341
|
+
}
|
342
|
+
|
343
|
+
@target = Target.new
|
344
|
+
end
|
345
|
+
|
346
|
+
it "should be error after tryed all druby uri" do
|
347
|
+
@target.druby_uris.first.should == @uris[0]
|
348
|
+
proc{ @target.queue_put }.should raise_error(::RuntimeError)
|
349
|
+
|
350
|
+
@target.druby_uris.first.should == @uris[0]
|
351
|
+
@target.druby_uris.size.should == @uris.size
|
352
|
+
(@target.druby_uris - @uris).should == []
|
353
|
+
end
|
354
|
+
|
355
|
+
it "should be not error after some node comes back" do
|
356
|
+
proc{ @target.queue_put }.should raise_error(::RuntimeError)
|
357
|
+
|
358
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
359
|
+
"druby://localhost:6438" => :inactive,
|
360
|
+
"druby://localhost:6439" => :active,
|
361
|
+
"druby://localhost:6440" => :inactive
|
362
|
+
}
|
363
|
+
|
364
|
+
@target.druby_uris.first.should == @uris[0]
|
365
|
+
proc{ @target.queue_put }.should_not raise_error
|
366
|
+
|
367
|
+
@target.druby_uris.first.should == @uris[1]
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
|
372
|
+
describe Ap4r::AsyncHelper::Base, "multiple URIs with all options and inactive 2nd server" do
|
373
|
+
|
374
|
+
before(:each) do
|
375
|
+
# configuration
|
376
|
+
@uris = %w(6438 6439 6440).map {|port| "druby://localhost:#{port}"}
|
377
|
+
::Ap4r::AsyncHelper::Base.druby_uris(@uris, :rotate => true, :fail_over => true, :fail_reuse => true)
|
378
|
+
|
379
|
+
# status
|
380
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
381
|
+
"druby://localhost:6438" => :active,
|
382
|
+
"druby://localhost:6439" => :inactive,
|
383
|
+
"druby://localhost:6440" => :active
|
384
|
+
}
|
385
|
+
|
386
|
+
@target = Target.new
|
387
|
+
end
|
388
|
+
|
389
|
+
it "should be not error on the first connection" do
|
390
|
+
proc { @target.queue_put }.should_not raise_error
|
391
|
+
end
|
392
|
+
|
393
|
+
it "should fail over on the second connection" do
|
394
|
+
@target.druby_uris.first.should == @uris[0]
|
395
|
+
@target.queue_put # connected to 6438
|
396
|
+
|
397
|
+
@target.druby_uris.first.should == @uris[1]
|
398
|
+
@target.queue_put # connected to 6440 and rotate next uri
|
399
|
+
|
400
|
+
@target.druby_uris.first.should == @uris[0]
|
401
|
+
end
|
402
|
+
|
403
|
+
it "should reuse the uri which it was inactive after it comes back" do
|
404
|
+
2.times { @target.queue_put }
|
405
|
+
@target.druby_uris.first.should == @uris[0]
|
406
|
+
|
407
|
+
ReliableMsg::Queue.ap4r_servers_status = {
|
408
|
+
"druby://localhost:6438" => :active,
|
409
|
+
"druby://localhost:6439" => :active,
|
410
|
+
"druby://localhost:6440" => :active
|
411
|
+
}
|
412
|
+
|
413
|
+
@target.queue_put # connected to 6438
|
414
|
+
@target.queue_put # connected to 6439
|
415
|
+
|
416
|
+
@target.druby_uris.first.should == @uris[2]
|
417
|
+
end
|
418
|
+
end
|
@@ -96,7 +96,7 @@ describe "When block style API is used, " do
|
|
96
96
|
end
|
97
97
|
|
98
98
|
it "should return the urlencoded body." do
|
99
|
-
@message_builder.format_message_body.should == "
|
99
|
+
@message_builder.format_message_body.split("&").sort.should == ["key2=1","key1=value"].sort
|
100
100
|
end
|
101
101
|
|
102
102
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ap4r
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shunichi Shinohara
|
@@ -10,11 +10,12 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date:
|
13
|
+
date: 2009-03-19 00:00:00 +09:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: reliable-msg
|
18
|
+
type: :runtime
|
18
19
|
version_requirement:
|
19
20
|
version_requirements: !ruby/object:Gem::Requirement
|
20
21
|
requirements:
|
@@ -22,17 +23,9 @@ dependencies:
|
|
22
23
|
- !ruby/object:Gem::Version
|
23
24
|
version: 1.1.0
|
24
25
|
version:
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: activesupport
|
27
|
-
version_requirement:
|
28
|
-
version_requirements: !ruby/object:Gem::Requirement
|
29
|
-
requirements:
|
30
|
-
- - ">="
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: "0"
|
33
|
-
version:
|
34
26
|
- !ruby/object:Gem::Dependency
|
35
27
|
name: mongrel
|
28
|
+
type: :runtime
|
36
29
|
version_requirement:
|
37
30
|
version_requirements: !ruby/object:Gem::Requirement
|
38
31
|
requirements:
|
@@ -42,6 +35,7 @@ dependencies:
|
|
42
35
|
version:
|
43
36
|
- !ruby/object:Gem::Dependency
|
44
37
|
name: rake
|
38
|
+
type: :runtime
|
45
39
|
version_requirement:
|
46
40
|
version_requirements: !ruby/object:Gem::Requirement
|
47
41
|
requirements:
|
@@ -73,7 +67,9 @@ files:
|
|
73
67
|
- config/queues_disk.cfg
|
74
68
|
- config/queues_mysql.cfg
|
75
69
|
- config/queues_pgsql.cfg
|
70
|
+
- fresh_rakefile
|
76
71
|
- lib/ap4r.rb
|
72
|
+
- lib/ap4r/async_helper.rb
|
77
73
|
- lib/ap4r/carrier.rb
|
78
74
|
- lib/ap4r/db/migrate/001_reliable_msg_queue_and_topic.rb
|
79
75
|
- lib/ap4r/dispatcher.rb
|
@@ -101,6 +97,8 @@ files:
|
|
101
97
|
- lib/ap4r/version.rb
|
102
98
|
- lib/ap4r/xxx_create_table_for_saf.rb
|
103
99
|
- lib/ap4r/xxx_create_table_for_saf_to_postgresql.rb
|
100
|
+
- lib/tasks/ap4r.rb
|
101
|
+
- lib/tasks/databases.rake
|
104
102
|
- rails_plugin/ap4r/init.rb
|
105
103
|
- rails_plugin/ap4r/lib/ap4r/queue_put_stub.rb
|
106
104
|
- rails_plugin/ap4r/lib/ap4r/service_handler.rb
|
@@ -111,6 +109,7 @@ files:
|
|
111
109
|
- script/mongrel_ap4r
|
112
110
|
- script/start
|
113
111
|
- script/stop
|
112
|
+
- spec/local/async_helper_queue_put_spec.rb
|
114
113
|
- spec/local/dispatcher_base_spec.rb
|
115
114
|
- spec/local/message_builder_spec.rb
|
116
115
|
- spec/local/send_message_handler_spec.rb
|
@@ -139,11 +138,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
138
|
requirements: []
|
140
139
|
|
141
140
|
rubyforge_project: ap4r
|
142
|
-
rubygems_version: 1.
|
141
|
+
rubygems_version: 1.3.1
|
143
142
|
signing_key:
|
144
143
|
specification_version: 2
|
145
144
|
summary: Asynchronous Processing for Ruby.
|
146
145
|
test_files:
|
146
|
+
- spec/local/async_helper_queue_put_spec.rb
|
147
147
|
- spec/local/dispatcher_base_spec.rb
|
148
148
|
- spec/local/message_builder_spec.rb
|
149
149
|
- spec/local/send_message_handler_spec.rb
|