ap4r 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -116,6 +116,8 @@ module Ap4r::Mongrel
116
116
  listener do
117
117
  log "Starting AP4R Handler with #{defaults[:ap4r_config_file]}"
118
118
  uri "/", :handler => ::Ap4r::Mongrel::Ap4rHandler.new(defaults)
119
+ uri "/queues", :handler => ::Ap4r::Mongrel::Ap4rSendMessageHandler.new(defaults)
120
+ uri "/subscribes", :handler => ::Ap4r::Mongrel::Ap4rSubscribeMessageHandler.new(defaults)
119
121
  end
120
122
  setup_signals(settings)
121
123
  end
@@ -6,7 +6,7 @@ require 'active_support'
6
6
  require 'yaml'
7
7
  require 'thread'
8
8
  require 'pp'
9
-
9
+ require 'erb'
10
10
  require 'uuid'
11
11
  require 'reliable-msg'
12
12
 
@@ -19,21 +19,21 @@ require 'ap4r/carrier'
19
19
  module ReliableMsg #:nodoc:
20
20
 
21
21
  # = Dynamic configuration with ERb
22
- #
23
- # Some times you would like to inject dynamic values into your configuration file.
22
+ #
23
+ # Some times you would like to inject dynamic values into your configuration file.
24
24
  # In these cases, you can mix ERb in with your YAML to code some logic, like:
25
- #
25
+ #
26
26
  # <% acl = [] %>
27
27
  # <% for i in 1..100 %>
28
28
  # <% acl << "192.168.0.#{i}" %>
29
- # <% end %>
29
+ # <% end %>
30
30
  # acl: <%= acl.map{|ip| "allow #{ip}"}.join(' ')
31
31
  #
32
32
  class Config
33
-
33
+
34
34
  alias :load_no_create_original :load_no_create
35
35
  alias :load_or_create_original :load_or_create
36
-
36
+
37
37
  #--
38
38
  # TODO: should enhance YAML.load_documents instead of this method?, 2007/5/7 kato-k
39
39
  def load_no_create
@@ -47,7 +47,7 @@ module ReliableMsg #:nodoc:
47
47
  true
48
48
  end
49
49
  end
50
-
50
+
51
51
  #--
52
52
  # TODO: should enhance YAML.load_documents instead of this method?, 2007/5/7 kato-k
53
53
  def load_or_create
@@ -68,13 +68,13 @@ module ReliableMsg #:nodoc:
68
68
  @logger.info format(INFO_CREATED_CONFIG, @file)
69
69
  end
70
70
  end
71
-
71
+
72
72
  private
73
73
  def erb_render(configuration_content)
74
- ERB.new(configuration_content).result
74
+ ::ERB.new(configuration_content).result
75
75
  end
76
76
  end
77
-
77
+
78
78
  class QueueManager
79
79
 
80
80
  # Gets a queue name which has the most stale message.
@@ -7,14 +7,16 @@ require 'active_support'
7
7
  module ReliableMsg #:nodoc:
8
8
 
9
9
  # This class is too much experimental.
10
- # The aim: for performance monitoring, records unprocessed message count
10
+ # The aim: for performance monitoring, records unprocessed message count
11
11
  # in every queues at some interval.
12
12
  class RetentionHistory
13
13
  include DRbUndumped
14
14
 
15
- LOOP_INTERVAL = 1.seconds
16
- SHELF_LIFE = 10.minutes
17
- # SHELF_LIFE = 10.seconds
15
+ # to_i method is required for ActiveSupport 2.0 where return value of seconds method
16
+ # is not Fixnum.
17
+ LOOP_INTERVAL = 1.seconds.to_i
18
+ SHELF_LIFE = 10.minutes.to_i
19
+ # SHELF_LIFE = 10.seconds.to_i
18
20
  attr_reader :data
19
21
 
20
22
  def initialize(qm, logger, config)
@@ -31,7 +31,7 @@ module Ap4r
31
31
 
32
32
  def dumped_headers
33
33
  # The warning occurs when putting backslash into binaly type in PostgreSQL.
34
- if postgresql?
34
+ if self.class.postgresql?
35
35
  self.headers
36
36
  else
37
37
  Marshal::dump(self.headers)
@@ -40,7 +40,7 @@ module Ap4r
40
40
 
41
41
  def dumped_object
42
42
  # The warning occurs when putting backslash into binaly type in PostgreSQL.
43
- if postgresql?
43
+ if self.class.postgresql?
44
44
  self.object
45
45
  else
46
46
  Marshal::dump(self.object)
@@ -7,15 +7,14 @@ module Ap4r::Util #:nodoc:
7
7
  #
8
8
  # Client class for +QueueManager+.
9
9
  # This class wraps DRb client and provides some helper methods.
10
- # TODO: many drb calls are executed in a method call such as +list_queues+.
11
- # ParseTree is perhaps needed.
12
- # TODO: +Proc+ object cannnot be passed via DRb. ParseTree also?
10
+ # TODO: many drb calls are executed in a method call such as +list_queues+. 2006/09/22 by shino
11
+ # ParseTree is perhaps needed. Now ruby-parser is also available?
13
12
  class QueueClient
14
13
  CONFIG_DIR_DEFAULT = 'config'
15
14
  CONFIG_FILE_DEFAULT = 'queues.cfg'
16
15
 
17
16
  HOST_DEFAULT = 'localhost'
18
-
17
+
19
18
  DEFAULT_QUEUE_PREFIX = 'queue.test.'
20
19
  DEFAULT_QUEUE_SUFFIX = 'default'
21
20
  DEFAULT_MULTI_QUEUE = DEFAULT_QUEUE_PREFIX + '*'
@@ -57,7 +56,7 @@ module Ap4r::Util #:nodoc:
57
56
  def list_queues
58
57
  qm.store.queues.keys
59
58
  end
60
-
59
+
61
60
  def list_messages(suffix = DEFAULT_QUEUE_SUFFIX,
62
61
  prefix = DEFAULT_QUEUE_PREFIX)
63
62
  qm.store.queues[prefix.to_s + suffix.to_s]
data/lib/ap4r/version.rb CHANGED
@@ -8,7 +8,7 @@ module Ap4r
8
8
  module VERSION #:nodoc:
9
9
  MAJOR = 0
10
10
  MINOR = 3
11
- TINY = 5
11
+ TINY = 6
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY].join('.')
14
14
  end
@@ -4,7 +4,7 @@
4
4
 
5
5
  require 'reliable-msg'
6
6
  require 'ap4r/stored_message'
7
- require 'message_builder'
7
+ require 'ap4r/message_builder'
8
8
 
9
9
  module Ap4r
10
10
 
@@ -1,5 +1,3 @@
1
- require File.expand_path(File.dirname(__FILE__) + "/../lib/ap4r/service_handler.rb")
2
-
3
1
  namespace :test do
4
2
 
5
3
  # task :asyncs do
@@ -10,14 +8,14 @@ namespace :test do
10
8
  namespace :asyncs do
11
9
 
12
10
  desc "Start Rails and AP4R servers to test:asyncs:exec"
13
- task :arrange do |t|
11
+ task :arrange => :require_dependencies do |t|
14
12
  ap4r_handler = Ap4r::ServiceHandler.new
15
13
  ap4r_handler.start_rails_service
16
14
  ap4r_handler.start_ap4r_service
17
15
  end
18
16
 
19
17
  desc "Start Rails and AP4R servers to test:asyncs:exec"
20
- task :cleanup do |t|
18
+ task :cleanup => :require_dependencies do |t|
21
19
  ap4r_handler = Ap4r::ServiceHandler.new
22
20
  ap4r_handler.stop_ap4r_service
23
21
  ap4r_handler.stop_rails_service
@@ -30,6 +28,13 @@ namespace :test do
30
28
  end
31
29
  Rake::Task['test:asyncs:run'].comment = "Run the unit tests in test/async"
32
30
 
31
+ # service_handler.rb needs to require the following libraries.
32
+ # If reliable-msg's rails adapter is loaded before rails initialization,
33
+ # it may cause to uninitialization error because the adapter requires ActionController.
34
+ # So, the load of the following libraries is delayed with rake task.
35
+ task :require_dependencies do
36
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/ap4r/service_handler.rb")
37
+ end
33
38
  end
34
39
 
35
40
  end
@@ -0,0 +1,200 @@
1
+ require File.join(File.dirname(__FILE__), "../spec_helper")
2
+ require 'ap4r/message_builder'
3
+ # TODO: move message_builder.rb to lib directory below. 2008/01/18 kiwamu
4
+ # require File.join(File.dirname(__FILE__), "../../rails_plugin/ap4r/lib/message_builder")
5
+
6
+ describe "When simple API is used," do
7
+
8
+ describe Ap4r::MessageBuilder, " with an empty message" do
9
+ before(:all) do
10
+ empty_message = {}
11
+ @message_builder = Ap4r::MessageBuilder.new("queue_name", empty_message, {})
12
+ end
13
+
14
+ it "should have the right MIME header." do
15
+ pending("TODO: should modify implementation? 2008/01/18 kiwamu")
16
+ mime_type = @message_builder.message_headers["http_header_Content-type".to_sym]
17
+ mime_type.should == "application/x-www-form-urlencoded"
18
+ end
19
+
20
+ it "should have the given message." do
21
+ @message_builder.message_body.should == {}
22
+ end
23
+
24
+ it "should return also a empty string body after format." do
25
+ @message_builder.format_message_body.should == ""
26
+ end
27
+
28
+ end
29
+
30
+ describe Ap4r::MessageBuilder, " with a simple message" do
31
+ before(:all) do
32
+ message = {:foo => "bar"}
33
+ @message_builder = Ap4r::MessageBuilder.new("queue_name", message, {})
34
+ end
35
+
36
+ it "should have the right MIME header." do
37
+ pending("TODO: should modify implementation? 2008/01/18 kiwamu")
38
+ mime_type = @message_builder.message_headers["http_header_Content-type".to_sym]
39
+ mime_type.should == "application/x-www-form-urlencoded"
40
+ end
41
+
42
+ it "should have the given message." do
43
+ @message_builder.message_body.should == {:foo => "bar"}
44
+ end
45
+
46
+ it "should return the urlencoded body." do
47
+ @message_builder.format_message_body.should == "foo=bar"
48
+ end
49
+
50
+ end
51
+
52
+ describe Ap4r::MessageBuilder, " with a nested complicated message" do
53
+ before(:all) do
54
+ @message = {:a => {:b => "c", :d => { :e => "f", :g => "h"}}, :i => "j"}
55
+ @message_builder = Ap4r::MessageBuilder.new("queue_name", @message, {})
56
+ end
57
+
58
+ it "should have the given message." do
59
+ @message_builder.message_body.should == @message
60
+ end
61
+
62
+ it "should return the urlencoded body." do
63
+ query = @message_builder.format_message_body
64
+ query.split("&").sort.should == %w(a[b]=c a[d][e]=f a[d][g]=h i=j).sort
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+
71
+
72
+ describe "When block style API is used, " do
73
+
74
+ describe Ap4r::MessageBuilder, " assigned unknown format" do
75
+
76
+ before(:all) do
77
+
78
+ block = Proc.new do
79
+ body :key1, "value"
80
+ body :key2, 1
81
+ format :unknown_format
82
+ end
83
+
84
+ @message_builder = Ap4r::MessageBuilder.new("", {}, {})
85
+ @message_builder.instance_eval(&block)
86
+ end
87
+
88
+ it "should have the right MIME header." do
89
+ pending("TODO: should modify implementation? 2008/01/24 kiwamu")
90
+ mime_type = @message_builder.message_headers["http_header_Content-type".to_sym]
91
+ mime_type.should == "application/x-www-form-urlencoded"
92
+ end
93
+
94
+ it "should have the given message." do
95
+ @message_builder.message_body.should == {:key1 => "value", :key2 => 1}
96
+ end
97
+
98
+ it "should return the urlencoded body." do
99
+ @message_builder.format_message_body.should == "key1=value&key2=1"
100
+ end
101
+
102
+ end
103
+
104
+ describe Ap4r::MessageBuilder, " assigned text format" do
105
+
106
+ before(:all) do
107
+
108
+ block = Proc.new do
109
+ body :key1, "value"
110
+ body :key2, 1
111
+ format :text
112
+ end
113
+
114
+ @message_builder = Ap4r::MessageBuilder.new("", {}, {})
115
+ @message_builder.instance_eval(&block)
116
+ end
117
+
118
+ it "should have the right MIME header." do
119
+ mime_type = @message_builder.message_headers["http_header_Content-type".to_sym]
120
+ mime_type.should == "text/plain"
121
+ end
122
+
123
+ it "should return the to_s formatted body." do
124
+ @message_builder.format_message_body.should == {:key1 => "value", :key2 => 1}.to_s
125
+ end
126
+ end
127
+
128
+ describe Ap4r::MessageBuilder, " assigned xml format" do
129
+
130
+ before(:all) do
131
+
132
+ block = Proc.new do
133
+ body :key1, "value"
134
+ body :key2, 1
135
+ format :xml
136
+ end
137
+
138
+ @message_builder = Ap4r::MessageBuilder.new("", {}, {})
139
+ @message_builder.instance_eval(&block)
140
+ end
141
+
142
+ it "should have the right MIME header." do
143
+ mime_type = @message_builder.message_headers["http_header_Content-type".to_sym]
144
+ mime_type.should == "application/xml"
145
+ end
146
+
147
+ it "should return the xml formatted body." do
148
+ @message_builder.format_message_body.should == {:key1 => "value", :key2 => 1}.to_xml(:root => "root")
149
+ end
150
+ end
151
+
152
+ describe Ap4r::MessageBuilder, " assigned json format" do
153
+
154
+ before(:all) do
155
+
156
+ block = Proc.new do
157
+ body :key1, "value"
158
+ body :key2, 1
159
+ format :json
160
+ end
161
+
162
+ @message_builder = Ap4r::MessageBuilder.new("", {}, {})
163
+ @message_builder.instance_eval(&block)
164
+ end
165
+
166
+ it "should have the right MIME header." do
167
+ mime_type = @message_builder.message_headers["http_header_Content-type".to_sym]
168
+ mime_type.should == "application/json"
169
+ end
170
+
171
+ it "should return the json formatted body." do
172
+ @message_builder.format_message_body.should == {:key1 => "value", :key2 => 1}.to_json
173
+ end
174
+ end
175
+
176
+ describe Ap4r::MessageBuilder, " assigned yaml format" do
177
+
178
+ before(:all) do
179
+
180
+ block = Proc.new do
181
+ body :key1, "value"
182
+ body :key2, 1
183
+ format :yaml
184
+ end
185
+
186
+ @message_builder = Ap4r::MessageBuilder.new("", {}, {})
187
+ @message_builder.instance_eval(&block)
188
+ end
189
+
190
+ it "should have the right MIME header." do
191
+ mime_type = @message_builder.message_headers["http_header_Content-type".to_sym]
192
+ mime_type.should == "text/yaml"
193
+ end
194
+
195
+ it "should return the yaml formatted body." do
196
+ @message_builder.format_message_body.should == {:key1 => "value", :key2 => 1}.to_yaml
197
+ end
198
+ end
199
+
200
+ end
@@ -0,0 +1,109 @@
1
+ require File.join(File.dirname(__FILE__), "../spec_helper")
2
+
3
+ require "reliable-msg"
4
+ require "ap4r/mongrel"
5
+
6
+ describe Ap4r::Mongrel::Ap4rSendMessageHandler, " on accepting a simple message" do
7
+
8
+ def start_queue_manager
9
+ @manager = ::ReliableMsg::QueueManager.new(:config => "config/queues_disk.cfg")
10
+ @manager.start_original
11
+ end
12
+
13
+ before(:each) do
14
+ start_queue_manager
15
+ q = ::ReliableMsg::Queue.new "queue.test"
16
+ while q.get; end
17
+
18
+ params = {
19
+ Mongrel::Const::PATH_INFO => "/queue.test",
20
+ Mongrel::Const::REQUEST_METHOD => "POST",
21
+ }
22
+ class << params
23
+ def http_body
24
+ "hoge"
25
+ end
26
+ end
27
+
28
+ class MockSocket
29
+ def initialize;end
30
+ def closed?;false;end
31
+ end
32
+
33
+ @handler = Ap4r::Mongrel::Ap4rSendMessageHandler.new(nil)
34
+ @request = Mongrel::HttpRequest.new(params, nil, nil)
35
+ @response = Mongrel::HttpResponse.new(MockSocket.new)
36
+ @handler.process(@request, @response)
37
+ end
38
+
39
+ after(:each)do
40
+ @manager.stop_original
41
+ end
42
+
43
+ it "should have one message in the queue" do
44
+ q = ReliableMsg::Queue.new "queue.test"
45
+ q.get.should_not be_nil
46
+ q.get.should be_nil
47
+ end
48
+
49
+ it "should have the same message body as http body" do
50
+ q = ReliableMsg::Queue.new "queue.test"
51
+ q.get.object.should == "hoge"
52
+ end
53
+ end
54
+
55
+ describe Ap4r::Mongrel::Ap4rSendMessageHandler, " on accepting a message with options" do
56
+
57
+ before(:each) do
58
+ @manager = ::ReliableMsg::QueueManager.new(:config => "config/queues_disk.cfg")
59
+ @manager.start_original
60
+
61
+ params = {
62
+ Mongrel::Const::PATH_INFO => "/queue.test",
63
+ Mongrel::Const::REQUEST_METHOD => "POST",
64
+ "HTTP_X_AP4R" => "priority=1, delivery=once, dispatch_mode=HTTP, target_method=POST, " +
65
+ "target_url=http://sample.com:3000"
66
+ }
67
+ class << params
68
+ def http_body
69
+ "hoge"
70
+ end
71
+ end
72
+
73
+ class MockSocket
74
+ def initialize;end
75
+ def closed?;false;end
76
+ end
77
+
78
+ @handler = Ap4r::Mongrel::Ap4rSendMessageHandler.new(nil)
79
+ @request = Mongrel::HttpRequest.new(params, nil, nil)
80
+ @response = Mongrel::HttpResponse.new(MockSocket.new)
81
+ @handler.process(@request, @response)
82
+ end
83
+
84
+ after(:each)do
85
+ @manager.stop_original
86
+ end
87
+
88
+ it "should have one message in the queue" do
89
+ q = ReliableMsg::Queue.new "queue.test"
90
+ q.get.should_not be_nil
91
+ q.get.should be_nil
92
+ end
93
+
94
+ it "should have the same message body as http body" do
95
+ q = ReliableMsg::Queue.new "queue.test"
96
+ q.get.object.should == "hoge"
97
+ end
98
+
99
+ it "should have the same message header as http header" do
100
+ q = ReliableMsg::Queue.new "queue.test"
101
+ m = q.get
102
+ m.headers[:priority].should == 1
103
+ m.headers[:delivery].should == :once
104
+ m.headers[:dispatch_mode].should == :HTTP
105
+ m.headers[:target_method].should == :POST
106
+ m.headers[:target_url].should == "http://sample.com:3000"
107
+ end
108
+
109
+ end