ap4r 0.3.6 → 0.3.7
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/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
|