ap4r 0.3.5 → 0.3.6
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 +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
|