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.
@@ -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