ap4r 0.3.5 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -2
- data/Manifest.txt +4 -1
- data/Rakefile +88 -36
- data/lib/ap4r/carrier.rb +3 -2
- data/lib/ap4r/dispatcher.rb +8 -2
- data/{rails_plugin/ap4r/lib → lib/ap4r}/message_builder.rb +3 -2
- data/lib/ap4r/message_store_ext.rb +19 -19
- data/lib/ap4r/mongrel.rb +192 -1
- data/lib/ap4r/mongrel_ap4r.rb +2 -0
- data/lib/ap4r/queue_manager_ext.rb +11 -11
- data/lib/ap4r/retention_history.rb +6 -4
- data/lib/ap4r/stored_message.rb +2 -2
- data/lib/ap4r/util/queue_client.rb +4 -5
- data/lib/ap4r/version.rb +1 -1
- data/rails_plugin/ap4r/lib/async_helper.rb +1 -1
- data/rails_plugin/ap4r/tasks/ap4r.rake +9 -4
- data/spec/local/message_builder_spec.rb +200 -0
- data/spec/local/send_message_handler_spec.rb +109 -0
- data/spec/local/subscribe_message_handler_spec.rb +51 -0
- metadata +85 -72
data/History.txt
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
== 0.3.x
|
2
2
|
|
3
|
+
=== 0.3.6 (February 6, 2008)
|
4
|
+
* Added: configuration to set HTTP timeout.
|
5
|
+
Based on a patch from Artem Vasiliev <abublic at gmail.com>
|
6
|
+
* Added: provisional support Rails2.0.
|
7
|
+
* Changed: the location of message_builder.rb from rails plugin to ap4r core (ap4r/lib directory).
|
8
|
+
* Fixed: bug (tracker #17206) that uninitialized constant error occurs when :active_record_store is used as session store.
|
9
|
+
|
3
10
|
=== 0.3.5 (November 29, 2007)
|
4
|
-
* Fixed: bug that SAF transaction is NOT guaranteed when some models are created/updated
|
5
|
-
before using of ap4r.async_to API in ap4r.transaction block.
|
11
|
+
* Fixed: bug that SAF transaction is NOT guaranteed when some models are created/updated before using of ap4r.async_to API in ap4r.transaction block.
|
6
12
|
|
7
13
|
=== 0.3.4 (October 31, 2007)
|
8
14
|
* Added: Support ActiveRecord as reliable RDBMS persistence.
|
data/Manifest.txt
CHANGED
@@ -15,6 +15,7 @@ lib/ap4r.rb
|
|
15
15
|
lib/ap4r/carrier.rb
|
16
16
|
lib/ap4r/db/migrate/001_reliable_msg_queue_and_topic.rb
|
17
17
|
lib/ap4r/dispatcher.rb
|
18
|
+
lib/ap4r/message_builder.rb
|
18
19
|
lib/ap4r/message_store_ext.rb
|
19
20
|
lib/ap4r/mongrel.rb
|
20
21
|
lib/ap4r/mongrel_ap4r.rb
|
@@ -43,11 +44,13 @@ rails_plugin/ap4r/lib/ap4r/queue_put_stub.rb
|
|
43
44
|
rails_plugin/ap4r/lib/ap4r/service_handler.rb
|
44
45
|
rails_plugin/ap4r/lib/ap4r_client.rb
|
45
46
|
rails_plugin/ap4r/lib/async_helper.rb
|
46
|
-
rails_plugin/ap4r/lib/message_builder.rb
|
47
47
|
rails_plugin/ap4r/tasks/ap4r.rake
|
48
48
|
script/irm
|
49
49
|
script/mongrel_ap4r
|
50
50
|
script/start
|
51
51
|
script/stop
|
52
52
|
spec/local/dispatcher_base_spec.rb
|
53
|
+
spec/local/message_builder_spec.rb
|
54
|
+
spec/local/send_message_handler_spec.rb
|
55
|
+
spec/local/subscribe_message_handler_spec.rb
|
53
56
|
spec/spec_helper.rb
|
data/Rakefile
CHANGED
@@ -1,50 +1,54 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'hoe'
|
3
2
|
require 'erb'
|
3
|
+
require 'find'
|
4
4
|
require 'active_record'
|
5
5
|
require File.join(File.dirname(__FILE__), 'lib/ap4r', 'version')
|
6
6
|
|
7
|
-
|
8
|
-
hoe
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
begin
|
8
|
+
namespace :hoe do
|
9
|
+
require 'hoe'
|
10
|
+
|
11
|
+
hoe = Hoe.new('ap4r', Ap4r::VERSION::STRING) do |p|
|
12
|
+
p.author = ["Shunichi Shinohara", "Kiwamu Kato"]
|
13
|
+
p.changes = p.paragraphs_of('History.txt', 1..2).join("\n\n")
|
14
|
+
#p.clean_globs =
|
15
|
+
p.description = <<-EOF
|
13
16
|
Asynchronous Processing for Ruby.
|
14
17
|
EOF
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
18
|
+
p.email = %q{shinohara.shunichi@future.co.jp, kato.kiwamu@future.co.jp}
|
19
|
+
|
20
|
+
p.extra_deps << ['reliable-msg', '=1.1.0']
|
21
|
+
p.extra_deps << ['activesupport']
|
22
|
+
p.extra_deps << ['mongrel']
|
23
|
+
p.extra_deps << ['rake']
|
24
|
+
p.extra_deps << ['hoe']
|
25
|
+
|
26
|
+
p.name = 'ap4r'
|
27
|
+
p.need_tar = false
|
28
|
+
p.need_zip = false
|
29
|
+
p.rdoc_pattern = /^(lib|bin|ext|rails_plugin)|txt$/
|
30
|
+
|
31
|
+
#p.remote_rdoc_dir =
|
32
|
+
#p.rsync =
|
33
|
+
p.rubyforge_name = 'ap4r'
|
34
|
+
#p.spec_extra =
|
35
|
+
p.summary = 'Asynchronous Processing for Ruby.'
|
36
|
+
p.test_globs = 'spec/**/*_spec.rb'
|
37
|
+
p.url = 'http://ap4r.rubyforge.org/wiki/wiki.pl?HomePage'
|
38
|
+
p.version = Ap4r::VERSION::STRING
|
39
|
+
end
|
40
|
+
hoe.spec.dependencies.delete_if {|dep| dep.name == "hoe"}
|
38
41
|
|
42
|
+
end
|
43
|
+
rescue
|
39
44
|
end
|
40
|
-
task :pkg => "release:copy_plugin"
|
41
45
|
|
42
46
|
# AP4R release tasks --------------------------------------------------------
|
43
47
|
|
44
48
|
HelloWorld = '../samples/HelloWorld'
|
45
49
|
|
46
50
|
namespace :release do
|
47
|
-
desc "copy rails plugin from sample before gem build"
|
51
|
+
desc "copy rails plugin from sample before gem build"
|
48
52
|
task :copy_plugin do
|
49
53
|
# TODO: Should use file task ? 2007/09/27 by shino
|
50
54
|
FileUtils.rm_rf('./rails_plugin/ap4r')
|
@@ -61,8 +65,10 @@ namespace :release do
|
|
61
65
|
path_list = []
|
62
66
|
Find.find('.') do |path|
|
63
67
|
next unless File.file?(path)
|
68
|
+
next if path =~ /^\.\/coverage\//
|
64
69
|
next if path =~ /^\.\/doc\//
|
65
|
-
next if path =~
|
70
|
+
next if path =~ /^\.\/log\//
|
71
|
+
next if path =~ /\.svn|tmp$|CVS|\.msg$|\.idx$|\.state$|\#$|\~$/
|
66
72
|
path_list << path
|
67
73
|
end
|
68
74
|
|
@@ -79,7 +85,7 @@ namespace :release do
|
|
79
85
|
task :sample do
|
80
86
|
FileUtils.mkdir_p('./pkg/samples')
|
81
87
|
FileUtils.rm_rf('./pkg/samples/HelloWorld')
|
82
|
-
|
88
|
+
|
83
89
|
FileUtils.cp_r(HelloWorld, './pkg/samples/')
|
84
90
|
Find.find('./pkg/samples') do |path|
|
85
91
|
next unless File.file? path
|
@@ -89,12 +95,13 @@ namespace :release do
|
|
89
95
|
Dir.chdir('./pkg/samples/HelloWorld')
|
90
96
|
`rake db:migrate`
|
91
97
|
Dir.chdir('../../')
|
92
|
-
|
98
|
+
|
93
99
|
`tar czf HelloWorld-#{Ap4r::VERSION::STRING}.tar.gz ./samples/HelloWorld/`
|
94
100
|
Dir.chdir('../')
|
95
101
|
end
|
96
102
|
end
|
97
103
|
|
104
|
+
task :pkg => "release:copy_plugin"
|
98
105
|
|
99
106
|
# Spec tasks ----------------------------------------------------------------
|
100
107
|
require 'spec/rake/spectask'
|
@@ -111,10 +118,15 @@ namespace :spec do
|
|
111
118
|
Spec::Rake::SpecTask.new(flavor) do |t|
|
112
119
|
t.spec_files = FileList["spec/#{flavor}/**/*.rb"]
|
113
120
|
t.rcov = true
|
121
|
+
build_artifacts = ENV['CC_BUILD_ARTIFACTS']
|
122
|
+
t.rcov_dir = build_artifacts.nil? ? "coverage" : "#{build_artifacts}"
|
114
123
|
excludes = %w(^spec\/)
|
115
124
|
if ENV['GEM_HOME']
|
116
125
|
excludes << Regexp.escape(ENV['GEM_HOME'])
|
117
126
|
end
|
127
|
+
if ENV['RUBY_HOME']
|
128
|
+
excludes << Regexp.escape(ENV['RUBY_HOME'])
|
129
|
+
end
|
118
130
|
t.rcov_opts = ["--exclude" , excludes.join(","),
|
119
131
|
"--text-summary"]
|
120
132
|
end
|
@@ -140,7 +152,7 @@ task :stats => "release:copy_plugin" do
|
|
140
152
|
end
|
141
153
|
|
142
154
|
namespace :qdb do
|
143
|
-
desc "Make queue and topic tables through scripts in lib/ap4r/db/migrate."
|
155
|
+
desc "Make queue and topic tables through scripts in lib/ap4r/db/migrate."
|
144
156
|
task :migrate do
|
145
157
|
|
146
158
|
# Todo: configurable file name, 2007/10/01 kiwamu
|
@@ -159,3 +171,43 @@ namespace :qdb do
|
|
159
171
|
end
|
160
172
|
end
|
161
173
|
|
174
|
+
todos_dirs = %w(lib rails_plugin spec)
|
175
|
+
|
176
|
+
desc "List TODO comments in #{todos_dirs.join(", ")} directories"
|
177
|
+
task :todos => todos_dirs.map{ |dir| "todos:#{dir}" }
|
178
|
+
|
179
|
+
namespace :todos do
|
180
|
+
todos_dirs.each do |dir|
|
181
|
+
desc "List TODO comments in #{dir} directory"
|
182
|
+
task dir => "release:copy_plugin" do
|
183
|
+
print_todos(dir)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def print_todos(dir)
|
188
|
+
FileList.new("#{dir}/**/*.*").each do |file|
|
189
|
+
next unless FileTest.file?(file)
|
190
|
+
next if (results = todos(file)).empty?
|
191
|
+
|
192
|
+
puts file
|
193
|
+
results.each{ |r|
|
194
|
+
puts "L.#{"%4d" % r[:line]}: #{r[:msg]} -- #{r[:date]} by #{r[:by]}"
|
195
|
+
}
|
196
|
+
puts
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def todos(file)
|
201
|
+
pattern = /TODO\s*:?\s*(.*)\s+(\d{4}\/\d{2}\/\d{2})\s*,?(?:by)?\s*(\S+)/i
|
202
|
+
|
203
|
+
results = []
|
204
|
+
File.open(file, "r") do |f|
|
205
|
+
f.each_line do |line|
|
206
|
+
next unless pattern.match(line)
|
207
|
+
results << {:line => f.lineno, :by => $3, :date => $2, :msg => $1.strip}
|
208
|
+
end
|
209
|
+
end
|
210
|
+
results
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
data/lib/ap4r/carrier.rb
CHANGED
@@ -2,11 +2,12 @@
|
|
2
2
|
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
|
+
begin require 'rubygems'; rescue LoadError; end
|
6
|
+
|
5
7
|
require 'yaml'
|
6
8
|
require 'thread'
|
7
9
|
require 'pp'
|
8
10
|
require 'active_support'
|
9
|
-
|
10
11
|
require 'reliable-msg'
|
11
12
|
|
12
13
|
module Ap4r
|
@@ -80,7 +81,7 @@ module Ap4r
|
|
80
81
|
# local_queue = ReliableMsg::Queue.new queue_name
|
81
82
|
# local_queue.put m.object
|
82
83
|
# }.join
|
83
|
-
|
84
|
+
|
84
85
|
#version 2: store tx and set nil, and resotre tx after putting a message
|
85
86
|
begin
|
86
87
|
tx = Thread.current[ReliableMsg::Client::THREAD_CURRENT_TX]
|
data/lib/ap4r/dispatcher.rb
CHANGED
@@ -94,7 +94,7 @@ module Ap4r
|
|
94
94
|
# If no class for +dispatch_mode+, raises an exception.
|
95
95
|
def get_dispather_instance(dispatch_mode, message, conf_per_targets)
|
96
96
|
klass = @@subclasses[dispatch_mode]
|
97
|
-
raise "undefined dispatch mode #{
|
97
|
+
raise "undefined dispatch mode #{message.headers[:mode]}" unless klass
|
98
98
|
klass.new(message, conf_per_targets)
|
99
99
|
end
|
100
100
|
|
@@ -233,6 +233,12 @@ module Ap4r
|
|
233
233
|
headers = make_header
|
234
234
|
|
235
235
|
Net::HTTP.start(uri.host, uri.port) do |http|
|
236
|
+
# TODO: global configuration over dispatchers for each protocol should be considered, 2008/02/06 by kiwamu
|
237
|
+
# TODO: http open timeout should be considered, 2008/02/06 by kiwamu
|
238
|
+
if @conf['http'] && @conf['http']['timeout']
|
239
|
+
http.read_timeout = @conf['http']['timeout']
|
240
|
+
logger.info "set HTTP read timeout to #{http.read_timeout}s"
|
241
|
+
end
|
236
242
|
@response, = http.post(uri.path, @message.object, headers)
|
237
243
|
end
|
238
244
|
end
|
@@ -330,7 +336,7 @@ module Ap4r
|
|
330
336
|
#
|
331
337
|
class Druby < Base
|
332
338
|
dispatch_mode :druby
|
333
|
-
|
339
|
+
|
334
340
|
def invoke
|
335
341
|
object = DRbObject.new_with_uri(@message[:target_url])
|
336
342
|
object.method_missing(@message[:target_method].to_sym, @message.object)
|
@@ -3,6 +3,7 @@
|
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
5
|
require 'active_record'
|
6
|
+
require 'active_support'
|
6
7
|
|
7
8
|
module Ap4r #:nodoc:
|
8
9
|
|
@@ -81,7 +82,7 @@ module Ap4r #:nodoc:
|
|
81
82
|
when :json
|
82
83
|
set_content_type("application/json")
|
83
84
|
when :yaml
|
84
|
-
set_content_type("text/
|
85
|
+
set_content_type("text/yaml")
|
85
86
|
else
|
86
87
|
set_content_type("application/x-www-form-urlencoded")
|
87
88
|
end
|
@@ -124,7 +125,7 @@ module Ap4r #:nodoc:
|
|
124
125
|
when :text
|
125
126
|
return @message_body.to_s
|
126
127
|
when :xml
|
127
|
-
return @message_body.to_xml
|
128
|
+
return @message_body.to_xml(@to_xml_options)
|
128
129
|
when :json
|
129
130
|
return @message_body.to_json
|
130
131
|
when :yaml
|
@@ -23,14 +23,14 @@ module ReliableMsg #:nodoc:
|
|
23
23
|
queue == mq
|
24
24
|
end
|
25
25
|
}
|
26
|
-
}.map{|queue, messages|
|
26
|
+
}.map{|queue, messages|
|
27
27
|
[queue, messages[0][:created]]
|
28
28
|
}.min {|q1, q2|
|
29
29
|
q1[1] <=> q2[1]
|
30
30
|
}
|
31
31
|
queue_and_created ? queue_and_created[0] : nil
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
# Returns a message store from the specified configuration (previously
|
35
35
|
# created with configure).
|
36
36
|
#
|
@@ -60,7 +60,7 @@ module ReliableMsg #:nodoc:
|
|
60
60
|
rescue LoadError
|
61
61
|
require 'postgres-pr/connection'
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
require 'base64'
|
65
65
|
|
66
66
|
class PostgreSQL < Base #:nodoc:
|
@@ -206,10 +206,10 @@ module ReliableMsg #:nodoc:
|
|
206
206
|
end
|
207
207
|
|
208
208
|
def connection
|
209
|
-
Thread.current[THREAD_CURRENT_PGSQL] ||=
|
209
|
+
Thread.current[THREAD_CURRENT_PGSQL] ||=
|
210
210
|
# PGconn is overriding in this file, so is defined regardless of 'postgres' LoadError.
|
211
211
|
if Object.const_defined? :PGError
|
212
|
-
::PGconn.connect @config[:host], @config[:port], @config[:options], @config[:tty], @config[:database], @config[:username], @config[:password]
|
212
|
+
::PGconn.connect @config[:host], @config[:port], @config[:options], @config[:tty], @config[:database], @config[:username], @config[:password]
|
213
213
|
elsif Object.const_defined? :PostgresPR
|
214
214
|
::PostgresPR::Connection.new @config[:database], @config[:username], @config[:password], @config[:uri]
|
215
215
|
end
|
@@ -217,16 +217,16 @@ module ReliableMsg #:nodoc:
|
|
217
217
|
end
|
218
218
|
|
219
219
|
end
|
220
|
-
|
220
|
+
|
221
221
|
rescue LoadError
|
222
222
|
# do nothing
|
223
223
|
end
|
224
224
|
|
225
|
-
|
225
|
+
|
226
226
|
begin
|
227
227
|
# ActiveRecord
|
228
228
|
# Make sure we have a ActiveRecord library before creating this class,
|
229
|
-
# worst case we end up with a disk-based message store.
|
229
|
+
# worst case we end up with a disk-based message store.
|
230
230
|
begin
|
231
231
|
require 'active_record'
|
232
232
|
require 'ap4r/reliable_msg_queue'
|
@@ -274,7 +274,7 @@ module ReliableMsg #:nodoc:
|
|
274
274
|
|
275
275
|
|
276
276
|
def configuration
|
277
|
-
config = { "type"=>TYPE, "adapter"=>@config[:adapter], "host"=>@config[:host],
|
277
|
+
config = { "type"=>TYPE, "adapter"=>@config[:adapter], "host"=>@config[:host],
|
278
278
|
"username"=>@config[:username], "password"=>@config[:password], "database"=>@config[:database] }
|
279
279
|
config["port"] = @config[:port] if @config[:port]
|
280
280
|
config["socket"] = @config[:socket] if @config[:socket]
|
@@ -335,7 +335,7 @@ module ReliableMsg #:nodoc:
|
|
335
335
|
rescue Exception=>error
|
336
336
|
raise error
|
337
337
|
end
|
338
|
-
super
|
338
|
+
super
|
339
339
|
|
340
340
|
end
|
341
341
|
|
@@ -356,7 +356,7 @@ module ReliableMsg #:nodoc:
|
|
356
356
|
end
|
357
357
|
queue << headers unless added
|
358
358
|
end
|
359
|
-
|
359
|
+
|
360
360
|
::Ap4r::ReliableMsgTopic.find(:all).each do |message|
|
361
361
|
@topocs[message[:topic]] = Marshal::load(message[:headers])
|
362
362
|
end
|
@@ -391,8 +391,8 @@ module ReliableMsg #:nodoc:
|
|
391
391
|
rescue LoadError
|
392
392
|
# do nothing
|
393
393
|
end
|
394
|
-
|
395
|
-
|
394
|
+
|
395
|
+
|
396
396
|
class Memory < Base #:nodoc:
|
397
397
|
|
398
398
|
TYPE = self.name.split('::').last.downcase
|
@@ -443,7 +443,7 @@ module ReliableMsg #:nodoc:
|
|
443
443
|
@mutex.synchronize do
|
444
444
|
@memory_map[insert[:id]] = insert[:message]
|
445
445
|
end
|
446
|
-
end
|
446
|
+
end
|
447
447
|
super
|
448
448
|
@mutex.synchronize do
|
449
449
|
deletes.each do |delete|
|
@@ -476,7 +476,7 @@ if Object.const_defined? :PGError
|
|
476
476
|
maybe_result.clear
|
477
477
|
end
|
478
478
|
end
|
479
|
-
|
479
|
+
|
480
480
|
def quote str
|
481
481
|
# do nothing
|
482
482
|
str
|
@@ -510,15 +510,15 @@ if Object.const_defined? :PostgresPR
|
|
510
510
|
# do nothing
|
511
511
|
str
|
512
512
|
end
|
513
|
-
|
514
|
-
end
|
513
|
+
|
514
|
+
end
|
515
515
|
end
|
516
516
|
end
|
517
517
|
|
518
|
-
if ReliableMsg::MessageStore::Base.use_mysql_extention
|
518
|
+
if Object.const_defined?(:Mysql) && ReliableMsg::MessageStore::Base.use_mysql_extention
|
519
519
|
class Mysql #:nodoc:
|
520
520
|
alias original_query query
|
521
|
-
|
521
|
+
|
522
522
|
# In Ruby/MySQL, +query+ method does NOT care about a given block.
|
523
523
|
# To make it behave the same as MySQL/Ruby, this method adds iteration
|
524
524
|
# over query results.
|
data/lib/ap4r/mongrel.rb
CHANGED
@@ -55,7 +55,7 @@ module Ap4r
|
|
55
55
|
|
56
56
|
def initialize(options)
|
57
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.
|
58
|
+
# e.g. not to initialize message store, not to start dispatchers, etc.
|
59
59
|
|
60
60
|
# TODO what is "false" here? 2007/04/13 by shinohara
|
61
61
|
@files = ::Mongrel::DirHandler.new(options[:docroot], false)
|
@@ -100,5 +100,196 @@ module Ap4r
|
|
100
100
|
|
101
101
|
end
|
102
102
|
|
103
|
+
# This class is an experimental implementation of RESTified message API.
|
104
|
+
# Send to queue:
|
105
|
+
# using HTTP POST
|
106
|
+
# a message is sent as HTTP body which format is depending on MIME type
|
107
|
+
# (now supported only text/plain)
|
108
|
+
#
|
109
|
+
# options are sent as HTTP header which header name is "X-AP4R"
|
110
|
+
# url consists of prefix ("/queues") and queue name
|
111
|
+
#
|
112
|
+
#
|
113
|
+
# === Request example ===
|
114
|
+
# POST /queues/queue.test HTTP/1.1
|
115
|
+
# Content-Type: text/plain
|
116
|
+
# X-AP4R: dispatch_mode=HTTP, target_method=POST, target_url=http://localhost:3000/async_shop/execute_via_http/
|
117
|
+
#
|
118
|
+
# hoge
|
119
|
+
#
|
120
|
+
#
|
121
|
+
# === Response example ===
|
122
|
+
# HTTP/1.1 200 Ok
|
123
|
+
# Date: The, 11 Dec 2007 17:17:11 GMT
|
124
|
+
#
|
125
|
+
# 7bb181f0-7ee0-012a-300a-001560abd426
|
126
|
+
#
|
127
|
+
class Ap4rSendMessageHandler < ::Mongrel::HttpHandler
|
128
|
+
|
129
|
+
def initialize(options)
|
130
|
+
@tick = Time.now
|
131
|
+
@queues = {}
|
132
|
+
end
|
133
|
+
|
134
|
+
def process(request, response)
|
135
|
+
if response.socket.closed?
|
136
|
+
return
|
137
|
+
end
|
138
|
+
|
139
|
+
queue_name = request.params[::Mongrel::Const::PATH_INFO][1..-1]
|
140
|
+
header = make_header(request.params["HTTP_X_AP4R"]) # Todo: assign as constant 2007/11/27 by kiwamu
|
141
|
+
|
142
|
+
if "POST".include? request.params[::Mongrel::Const::REQUEST_METHOD]
|
143
|
+
begin
|
144
|
+
q = if @queues.key? queue_name
|
145
|
+
@queues[queue_name]
|
146
|
+
else
|
147
|
+
@queues[queue_name] = ::ReliableMsg::Queue.new(queue_name)
|
148
|
+
end
|
149
|
+
mid = q.put(request.body.string, header)
|
150
|
+
|
151
|
+
response.start(200) do |head, out|
|
152
|
+
head['Content-Type'] = 'text/plain'
|
153
|
+
out.write mid
|
154
|
+
end
|
155
|
+
rescue Exception
|
156
|
+
response.start(500) do |head, out|
|
157
|
+
head['Content-Type'] = 'text/plain'
|
158
|
+
out.write "Failed to send message. #{request.body.string}"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
else
|
162
|
+
raise "HTTP method is not POST..." # Todo
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def make_header(x_ap4r_header)
|
167
|
+
header = {}
|
168
|
+
if x_ap4r_header
|
169
|
+
x_ap4r_header.split(',').map do |e|
|
170
|
+
key, value = e.strip.split('=')
|
171
|
+
if %w(dispatch_mode target_method delivery).include?(key)
|
172
|
+
header[key.to_sym] = value.to_sym
|
173
|
+
else
|
174
|
+
header[key.to_sym] = value
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
header
|
179
|
+
end
|
180
|
+
|
181
|
+
def log_threads_waiting_for(event)
|
182
|
+
if Time.now - @tick > 10
|
183
|
+
@tick = Time.now
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Does the internal reload for Rails. It might work for most cases, but
|
188
|
+
# sometimes you get exceptions. In that case just do a real restart.
|
189
|
+
def reload!
|
190
|
+
begin
|
191
|
+
#TODO not implemented 2007/04/09 by shino
|
192
|
+
raise "not yet implemented!"
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
# This class is an experimental implementation of RESTified message API.
|
199
|
+
# Subscribe to queue:
|
200
|
+
# using HTTP POST
|
201
|
+
# a message is subscribed as HTTP body
|
202
|
+
#
|
203
|
+
# options are sent as HTTP header which header name is "X-AP4R"
|
204
|
+
# (now not supported)
|
205
|
+
#
|
206
|
+
# url consists of prefix ("/subscribes") and queue name
|
207
|
+
#
|
208
|
+
# response body is now return value of ReliableMsg#inspct
|
209
|
+
# In the future, it will be possible to assign the format by the request header X-AP4R
|
210
|
+
#
|
211
|
+
#
|
212
|
+
# === Rrequest example ===
|
213
|
+
# POST /subscribes/queue.test HTTP/1.1
|
214
|
+
#
|
215
|
+
#
|
216
|
+
# === Response example ===
|
217
|
+
# HTTP/1.1 200 Ok
|
218
|
+
# Content-Type: text/plain
|
219
|
+
# Date: The, 11 Dec 2007 17:17:11 GMT
|
220
|
+
#
|
221
|
+
# #<ReliableMsg::Message:0x320ec90 @headers={:priority=>0, :created=>1197628231, :expires=>nil, :delivery=>:best_effort, :id=>\"856016b0-8c5d-012a-79f3-0016cb9ad524\", :max_deliveries=>5}, @object=\"hoge\", @id=\"856016b0-8c5d-012a-79f3-0016cb9ad524\">
|
222
|
+
#
|
223
|
+
class Ap4rSubscribeMessageHandler < ::Mongrel::HttpHandler
|
224
|
+
|
225
|
+
def initialize(options)
|
226
|
+
@tick = Time.now
|
227
|
+
@queues = {}
|
228
|
+
end
|
229
|
+
|
230
|
+
def process(request, response)
|
231
|
+
if response.socket.closed?
|
232
|
+
return
|
233
|
+
end
|
234
|
+
|
235
|
+
queue_name = request.params[::Mongrel::Const::PATH_INFO][1..-1]
|
236
|
+
# header = make_header(request.params["HTTP_X_AP4R"]) # Todo: assign as constant 2007/11/27 by kiwamu
|
237
|
+
|
238
|
+
if "POST".include? request.params[::Mongrel::Const::REQUEST_METHOD]
|
239
|
+
begin
|
240
|
+
q = if @queues.key? queue_name
|
241
|
+
@queues[queue_name]
|
242
|
+
else
|
243
|
+
@queues[queue_name] = ::ReliableMsg::Queue.new(queue_name)
|
244
|
+
end
|
245
|
+
mes = q.get
|
246
|
+
|
247
|
+
response.start(200) do |head, out|
|
248
|
+
head['Content-Type'] = 'text/plain'
|
249
|
+
out.write mes.inspect
|
250
|
+
end
|
251
|
+
rescue
|
252
|
+
response.start(500) do |head, out|
|
253
|
+
head['Content-Type'] = 'text/plain'
|
254
|
+
out.write "Failed to get message for #{queue_name}"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
else
|
258
|
+
raise "HTTP method is not POST..."
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def make_header(x_ap4r_header)
|
263
|
+
header = {}
|
264
|
+
if x_ap4r_header
|
265
|
+
x_ap4r_header.split(',').map do |e|
|
266
|
+
key, value = e.strip.split('=')
|
267
|
+
if %w(dispatch_mode target_method delivery).include?(key)
|
268
|
+
header[key.to_sym] = value.to_sym
|
269
|
+
else
|
270
|
+
header[key.to_sym] = value
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
header
|
275
|
+
end
|
276
|
+
|
277
|
+
def log_threads_waiting_for(event)
|
278
|
+
if Time.now - @tick > 10
|
279
|
+
@tick = Time.now
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# Does the internal reload for Rails. It might work for most cases, but
|
284
|
+
# sometimes you get exceptions. In that case just do a real restart.
|
285
|
+
def reload!
|
286
|
+
begin
|
287
|
+
#TODO not implemented 2007/04/09 by shino
|
288
|
+
raise "not yet implemented!"
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
end
|
293
|
+
|
103
294
|
end
|
104
295
|
end
|