This document provides an overview of a presentation titled "AP4R" given at RubyConf 07 by Kiwamu Kato and Shun'ichi Shinohara of Future Architect, Inc. It introduces AP4R as an asynchronous processing library for Ruby that uses messaging to enable loose coupling. Key points covered include the motivation for developing AP4R based on their experience with an in-house messaging middleware, typical use cases for load distribution and quicker response times, and advantages like being lightweight, robust, and having simple APIs. Examples of companies using AP4R are also provided.
6. shino
• Made a debut to the OSS world
last year
• http://d.hatena.ne.jp/ita-wasa
• Sunday physicist,
interested in the string theory
6
7. Corporate profile
• Future Architect, Inc.
• http://www.future.co.jp/en/index.html
• Aiming for optimization and synergy of
business and IT
• Headquarters: Tokyo, Japan
• Foundation: November 28, 1989
• Number of employees: 594 (as of June 2007)
• Revenue: ¥14,831M (2006)
7
8. Agenda
1. Overview ( the most important part. )
2. Lightweight
3. Demo
4. Robust
5. Other features
6. Conclusion
8
19. From RtFA to AP4R
• Based on experiences of Java,
carefully designed to keep good concepts and
added “agility”
• Focused on ease of use API, configuration
19
20. Open source
• Released as OSS last year
• Take advantages of the community
• For “Enterprise”
20
21. Typical use cases of AP4R
• Quicker response to users
• Load distribution
21
41. AP4R realized
• Ease of use
• Simple API / configuration
• Seamless collaboration with Rails
• All-in-one support
• Not only development
• But also test and operation support
38
58. What is it ?
• From England
• Massively multiplayer web-based
strategy game
• Late alpha now;
private beta testing in January 2008
55
59. They use AP4R for
• Mail sending
• Report generation
• Data analysis routines
• A variety of processor-intensive
processes including database access
56
60. Scale
• Two dedicated AP4R servers
• Four Rails processes per AP4R
• A few hundred messages an hour
• MySQL to store messages
57
63. What is it ?
• From the U.S.
• Provide mobile messaging solutions for clients, as
well as internal products like TextMe for Business
( http://textmeforbusiness.com )
• In production since July 2007
60
65. They use AP4R for
• Intersystem connection
• Inbound queue
• Outbound queue
• Routing queue
• Text processing
62
66. Alert service on SMS
AP4R queues
acceptance
inbound Text
processing
delivery delivery
outbound
delivery
processing
Third Party
routing application
63
67. Scale
• Three AP4R processes
• Four mongrel clusters and so forth
• Now at least a thousand messages a day
( Several thousand messages a day soon )
• MySQL to store messages
64
69. Questionnaire results
• “Easy to distribute a kind of load across
a number of servers”
• “Easy to scale”
• “Development is active”
• “Development team had real-world experience
with the technology”
66
143. Ap4r::Client#transaction
Class ShopController < ApplicationController
def order # synchronous side
ap4r.transaction do
o = Order.new(:name => params[:order_id])
o.save!
ap4r.async_to({:action => ‘payment’},
{:order_id => o.id})
end
redirect_to ...
end
end
134
204. ☺
It makes us feel relieved in
developing an application
161
205. On async app.
• Test matters also, but ..
• Multiple processes
communicating via N/W
• take time
• annoying to setup
162
206. Two ways of testing
• Functional test
• no N/W communication
• fast but restricted
• Async test
• using N/W communication
• slow but close to actual
163
208. code sample
test code here is against a ‘fictional’ on-line shop
application, which has an order action (sync)
and payment action (async).
165
209. def test_order
post :order, :order => {:item => quot;introduction to AP4Rquot;}
assert_response :redirect
assert_redirected_to :action => 'index'
messages = @controller.ap4r.queued_messages # ... (1)
assert_equal 1, messages.keys.size, quot;should have messages in just ONE queuequot;
assert messages.key?(quot;queue.async_shop.paymentquot;), quot;queue name is INCORRECTquot;
# ... (2)
assert_equal 1, messages[quot;queue.async_shop.paymentquot;].size,
quot;should have just ONE message for paymentquot;
assert_match /order_id=d+/, messages[quot;queue.async_shop.paymentquot;].first[:body],
quot;parameter order_id should be included with a numeric valuequot; # ... (3)
end
1. get (stubbed)queued messages
2. assert the queue name
3. assert the message content
166
213. [RAILS_ROOT]/test/async/ap4r_test_helper.rb
ENV[quot;RAILS_ENVquot;] = quot;testquot;
require File.expand_path(File.dirname(__FILE__) + quot;/../../config/environmentquot;)
require quot;ap4r/service_handlerquot;
ap4r_test_helper = Ap4r::ServiceHandler.new
require 'test_help'
class Test::Unit::TestCase
self.use_transactional_fixtures = false
self.use_instantiated_fixtures = false
# Add more helper methods to be used by all tests here...
cattr_accessor :ap4r_helper
def ap4r_helper
@@ap4r_helper
end
def with_services(&block)
ap4r_helper.with_services(&block)
end
end
Test::Unit::TestCase.ap4r_helper = ap4r_test_helper
170
214. [RAILS_ROOT]/test/async/async_shop_test.rb
require quot;#{File.dirname(__FILE__)}/ap4r_test_helperquot;
require 'net/http'
class AsyncShopTest < Test::Unit::TestCase
def test_http_dispatch
ap4r_helper.stop_dispatchers # ... (1)
assert_rows_added(Order, 1) { # ... (3)
do_order # ... (2)
}
assert_rows_added(Payment, 1) { # ... (6)
ap4r_helper.start_dispatchers # ... (4)
ap4r_helper.wait_all_done # ... (5)
}
end
private
# Requests to <tt>async_shop/order</tt>.
def do_order(item_name = quot;test itemquot;)
Net::HTTP.start(quot;localhostquot;, 3000, nil, nil) do |http|
http.request_post(quot;/async_shop/orderquot;,
quot;order[item]=#{item_name}quot;) do |res|
#nop
end
end
end
def assert_rows_added(model, rows)
rows_before = model.count
yield
rows_after = model.count
assert_equal rows, rows_after - rows_before, quot;table '#{model.table_name}' should count up by #{rows}quot;
end
end
171
215. stop dispatcher threads
1.
request to Rails with HTTP POST
2.
assert one row added to orders table
3.
start dispatcher threads
4.
wait for async action is completed
5.
assert one row added to payments table
6.
172
216. async test
rake ..
service control
HTTP
CRUD
message put
assert
HTTP
CRUD
assert
173
217. Summary
• Two test methods.
• Functional test
• Async test
• It makes us feel relieved to
develop an application
174
230. • Future Architect logo belongs to Future Architect, Inc.
Japan. All rights reserved.
• Rails logo is trademarks of David Heinemeier
Hansson. All rights reserved.
• The Ruby logo is copyrighted (c) 2006, Yukihiro
Matsumoto. It is released under the terms of the
Creative Commons Attribution-ShareAlike 2.5 License.
187