ap4r 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -3
- data/MIT-LICENSE +1 -1
- data/README +196 -52
- data/Rakefile +133 -15
- data/bin/ap4r_setup +6 -0
- data/config/ap4r_settings.rb +5 -0
- data/{configs → config}/log4r.yaml +0 -0
- data/{configs → config}/queues.cfg +0 -0
- data/config/queues_disk.cfg +15 -0
- data/{configs → config}/queues_mysql.cfg +6 -2
- data/lib/ap4r.rb +7 -9
- data/lib/ap4r/message_store_ext.rb +26 -0
- data/lib/ap4r/multi_queue.rb +19 -0
- data/lib/ap4r/queue_manager_ext.rb +18 -4
- data/lib/ap4r/queue_manager_ext_debug.rb +13 -0
- data/lib/ap4r/retention_history.rb +7 -0
- data/lib/ap4r/script/base.rb +11 -0
- data/lib/ap4r/script/queue_manager_control.rb +27 -0
- data/lib/ap4r/script/setup.rb +17 -0
- data/lib/ap4r/script/workspace_generator.rb +65 -0
- data/lib/ap4r/start_with_log4r.rb +4 -0
- data/lib/ap4r/util/irm.rb +93 -0
- data/lib/ap4r/util/loc.rb +12 -0
- data/lib/ap4r/util/queue_client.rb +123 -0
- data/lib/ap4r/version.rb +15 -0
- data/rails_plugin/ap4r/init.rb +10 -0
- data/rails_plugin/ap4r/lib/async_controller.rb +64 -0
- data/script/irm +4 -0
- data/{bin → script}/loop.cmd +0 -0
- data/{bin → script}/loop.rb +0 -0
- data/script/start +5 -0
- data/script/stop +1 -0
- metadata +53 -31
- data/bin/ap4r +0 -0
- data/bin/irm.cmd +0 -2
- data/bin/queues.cmd +0 -2
- data/bin/queues.rb +0 -3
- data/bin/stop.cmd +0 -1
- data/configs/queues_disk.cfg +0 -15
- data/lib/ap4r/utils/irm.rb +0 -109
- data/lib/ap4r/utils/loc.rb +0 -8
data/CHANGELOG
CHANGED
data/MIT-LICENSE
CHANGED
data/README
CHANGED
@@ -1,52 +1,196 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
1
|
+
== What is AP4R?
|
2
|
+
|
3
|
+
AP4R, Asynchronous Processing for Ruby, is the implementation of reliable asynchronous message processing. It provides message queuing, and message dispatching.
|
4
|
+
Using asynchronous processing, we can cut down turn-around-time of web applications by queuing, or can utilize more machine power by load-balancing.
|
5
|
+
Also AP4R nicely ties with your Ruby on Rails applications. See Hello World sample application from rubyforge.
|
6
|
+
|
7
|
+
http://rubyforge.org/projects/ap4r/
|
8
|
+
|
9
|
+
== Features
|
10
|
+
|
11
|
+
1. Business logics can be implemented as simple Web applications, or ruby code, whether it's called asynchronously or synchronously.
|
12
|
+
1. Asynchronous messaging is reliable by RDBMS persistence (now MySQL only) or file persistence, under the favor of reliable-msg.
|
13
|
+
1. Load balancing over multiple AP4R processes on single/multiple servers is supported.
|
14
|
+
1. Asynchronous logics are called via various protocols, such as XML-RPC, SOAP, HTTP PUT, and more. (now implemented just as XML-RPC)
|
15
|
+
|
16
|
+
== Typical process flow
|
17
|
+
|
18
|
+
1. A client(e.g. a web browser) makes a request to a web server (Apache, Lighttpd, etc...).
|
19
|
+
1. A rails application (a synchronous logic) is executed on mongrel via mod_proxy or something.
|
20
|
+
1. At the last of the synchronous logic, message(s) are put to AP4R (AP4R provides a helper).
|
21
|
+
1. Once the synchronous logic is done, the clients receives a response immediately.
|
22
|
+
1. AP4R queues the message, and requests it to the web server asynchronously.
|
23
|
+
1. An asynchronous logic, implemented as usual rails action, is executed.
|
24
|
+
|
25
|
+
|
26
|
+
== Installation
|
27
|
+
|
28
|
+
Use RubyGems command.
|
29
|
+
|
30
|
+
$ sudo gem install ap4r --include-dependencies
|
31
|
+
|
32
|
+
|
33
|
+
== Working directory
|
34
|
+
|
35
|
+
Create your working directory (ex. my_work) wherever you want.
|
36
|
+
|
37
|
+
$ ap4r_setup my_work
|
38
|
+
$ cd my_work
|
39
|
+
|
40
|
+
Its structure is as follows.
|
41
|
+
|
42
|
+
my_work
|
43
|
+
+-- config
|
44
|
+
+-- log
|
45
|
+
+-- script
|
46
|
+
+-- tmp
|
47
|
+
|
48
|
+
== Message Persistence
|
49
|
+
|
50
|
+
AP4R uses reliable-msg for message persistence. It enables disk or RDBMS persistence. See references for details of reliable-msg. Install MySQL if you choose MySQL persistence. We recommend to install MySQL/Ruby library to connect to MySQL. For convinience, Ruby/MySQL bundled in the ActiveRecord gem can be used.
|
51
|
+
Create a table in your database. (If you use topics via reliable-msg, create another slightly different table.)
|
52
|
+
|
53
|
+
CREATE TABLE `reliable_msg_queues` (
|
54
|
+
`id` varchar(255) NOT NULL default '',
|
55
|
+
`queue` varchar(255) NOT NULL default '',
|
56
|
+
`headers` text NOT NULL,
|
57
|
+
`object` blob NOT NULL,
|
58
|
+
PRIMARY KEY (`id`)
|
59
|
+
) ENGINE=InnoDB DEFAULT CHARSET=binary;
|
60
|
+
|
61
|
+
== Configuration file
|
62
|
+
|
63
|
+
A command ap4r_setup have created a template configuration file (my_work/config/queues.cfg).
|
64
|
+
|
65
|
+
---
|
66
|
+
store:
|
67
|
+
type: mysql
|
68
|
+
host: localhost
|
69
|
+
database: test
|
70
|
+
username: test
|
71
|
+
password:
|
72
|
+
drb:
|
73
|
+
host:
|
74
|
+
port: 6438
|
75
|
+
acl: allow 127.0.0.1
|
76
|
+
dispatchers:
|
77
|
+
-
|
78
|
+
targets: queue.*
|
79
|
+
threads: 1
|
80
|
+
#carriers:
|
81
|
+
# -
|
82
|
+
# source_uri: druby://another.host.local:6438
|
83
|
+
# threads: 1
|
84
|
+
|
85
|
+
queues.cfg has four parts.
|
86
|
+
|
87
|
+
* persistent role (store: )
|
88
|
+
* Set database or file information.
|
89
|
+
|
90
|
+
* message listener (drb:)
|
91
|
+
* Set IP, and port number which are used by clients.
|
92
|
+
* acl = access control list, exmaple below.
|
93
|
+
|
94
|
+
allow 127.0.0.1 allow 10.0.0.0/8 deny 192.168.0.1
|
95
|
+
|
96
|
+
* asynchronous process invokers (dispatchers:)
|
97
|
+
* Dispatchers handle messages in queues specified by targets,
|
98
|
+
* with as many threads as specified by threads.
|
99
|
+
* Each thread waits (is blocked) until the invocation returns.
|
100
|
+
|
101
|
+
* message routing (carriers:) # EXPERIMENTAL
|
102
|
+
* Carriers get messages from an AP4R server specified by source_uri,
|
103
|
+
* with as many threads as specified by threads,
|
104
|
+
* and put messages to a local AP4R server.
|
105
|
+
|
106
|
+
== Monitoring
|
107
|
+
|
108
|
+
Future plan: connections with monitoring tools such as Cacti and ZABBIX.
|
109
|
+
|
110
|
+
* Cacti
|
111
|
+
* http://www.cacti.net/
|
112
|
+
* ZABBIX
|
113
|
+
* http://www.zabbix.org/
|
114
|
+
|
115
|
+
== Sample - HelloWorld -
|
116
|
+
|
117
|
+
There is an asynchronous application sample with file persistence, where a synchronous logic outputs "Hello" to a file, and an asynchronous logic appends "World".
|
118
|
+
Once the synchronous logic has done, a client (a web browser) displays response, and there is only "Hello" in a file.
|
119
|
+
Since the asynchronous logic sleeps ten seconds and appends to the file, wait briefly and you can see whole "HelloWorld" in the file
|
120
|
+
|
121
|
+
* Install Ruby, Rails and AP4R and configure AP4R in reference above sections
|
122
|
+
* No need for MySQL.
|
123
|
+
|
124
|
+
* Make sample application available
|
125
|
+
* If you have an SVN client,
|
126
|
+
|
127
|
+
$ svn co svn://rubyforge.org/var/ap4r/tags/ap4r-0.1.0/sample [some directory]
|
128
|
+
|
129
|
+
* Unless
|
130
|
+
1. download the sample from RubyForge
|
131
|
+
http://rubyforge.org/projects/ap4r/
|
132
|
+
filename: HelloWorld.zip
|
133
|
+
|
134
|
+
1. and extract to an appropricate directory(ex. HelloWorld ).
|
135
|
+
There are app/, components/,... directories under HelloWorld.
|
136
|
+
|
137
|
+
* Start WEBRick.
|
138
|
+
* In a command line
|
139
|
+
|
140
|
+
$ cd HelloWorld
|
141
|
+
$ ruby script\server
|
142
|
+
|
143
|
+
* If you see Welcome screen at http://localhost:3000, it's ok.
|
144
|
+
|
145
|
+
* Start AP4R.
|
146
|
+
* In another command line,
|
147
|
+
* start AP4R with specifying the configuraion file.
|
148
|
+
|
149
|
+
$ cd my_work
|
150
|
+
$ ruby script/start -c config/queues_disk.cfg
|
151
|
+
|
152
|
+
* Execute a synchronous logic.
|
153
|
+
* http://localhost:3000/sync_hello/execute
|
154
|
+
* A file HelloWorld.txt is creted under HelloWorld/ which contains a word "Hello".
|
155
|
+
|
156
|
+
* Confirm the execution of an asynchronous logic.
|
157
|
+
* Wait ten seconds,
|
158
|
+
* and look into the file HelloWorld.txt again, there must be "HelloWorld".
|
159
|
+
|
160
|
+
* Think of application to your real application
|
161
|
+
* This mechanism can work in general applications.
|
162
|
+
* An order acceptance logic instead of printing "Hello".
|
163
|
+
* Asynchronous logic of auto shipping order or accounting instead of appending "World".
|
164
|
+
|
165
|
+
== Future Plan
|
166
|
+
|
167
|
+
* add protocols to invoke asynchronous logics
|
168
|
+
* only-once QoS
|
169
|
+
* at-lease-once QoS
|
170
|
+
* DLQ recovery
|
171
|
+
* flow volume control, load balancing
|
172
|
+
* 7x24 support (e.g. rolling database tables)
|
173
|
+
* monitoring (e.g. thread status, web frontend)
|
174
|
+
* Coordination with Ruby on Rails, such as development/testing lifesycle support.
|
175
|
+
|
176
|
+
== References
|
177
|
+
|
178
|
+
* Ruby Homepage
|
179
|
+
* http://www.ruby-lang.org/
|
180
|
+
* Ruby on Rails tutorial
|
181
|
+
* http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html
|
182
|
+
* MySQL tutorial
|
183
|
+
* http://dev.mysql.com/doc/refman/5.0/en/index.html
|
184
|
+
* reliable-msg
|
185
|
+
* http://trac.labnotes.org/cgi-bin/trac.cgi/wiki/Ruby/ReliableMessaging
|
186
|
+
|
187
|
+
== Licence
|
188
|
+
|
189
|
+
This licence is licensed under the MIT license.
|
190
|
+
Copyright(c) 2006 Future System Consulting Corp.
|
191
|
+
|
192
|
+
== Authors
|
193
|
+
|
194
|
+
* Kiwamu Kato
|
195
|
+
* Shunichi Shinohara
|
196
|
+
|
data/Rakefile
CHANGED
@@ -1,25 +1,143 @@
|
|
1
|
-
|
1
|
+
# Author:: Kiwamu Kato
|
2
|
+
# Copyright:: Copyright (c) 2006 Future System Consulting Corp.
|
3
|
+
# Licence:: MIT Licence
|
4
|
+
|
2
5
|
require 'rake'
|
3
6
|
require 'rake/testtask'
|
4
7
|
require 'rake/rdoctask'
|
5
|
-
require 'rake/packagetask'
|
6
8
|
require 'rake/gempackagetask'
|
7
9
|
require 'rake/contrib/rubyforgepublisher'
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
require 'date'
|
12
|
+
require 'find'
|
13
|
+
require 'rbconfig'
|
14
|
+
|
15
|
+
require File.join(File.dirname(__FILE__), 'lib/ap4r', 'version')
|
16
|
+
|
17
|
+
PKG_VERSION = AP4R::VERSION::STRING
|
18
|
+
|
19
|
+
TEMP_DIR = './temp'
|
20
|
+
PKG_DIR = './pkg'
|
21
|
+
RELEASE_DIR = './release'
|
22
|
+
HELLO_WORLD_DIR = '../samples/HelloWorld'
|
23
|
+
|
24
|
+
# Generate GEM ----------------------------------------------------------------------------
|
25
|
+
|
26
|
+
|
27
|
+
PKG_FILES = FileList[
|
28
|
+
'[a-zA-Z]*',
|
29
|
+
'bin/**/*',
|
30
|
+
'config/**/*',
|
31
|
+
'rails_plugin/**/*',
|
32
|
+
'script/**/*',
|
33
|
+
'lib/**/*'
|
34
|
+
]
|
35
|
+
|
36
|
+
HELLO_WORLD_SAMPLE_FILES = FileList[
|
37
|
+
'[a-zA-Z]*',
|
38
|
+
'app/**/*',
|
39
|
+
'components/**/*',
|
40
|
+
'config/**/*',
|
41
|
+
'db/**/*',
|
42
|
+
'doc/**/*',
|
43
|
+
'lib/**/*',
|
44
|
+
'log/**/*',
|
45
|
+
'public/**/*',
|
46
|
+
'script/**/*',
|
47
|
+
'test/**/*',
|
48
|
+
'tmp/**/*',
|
49
|
+
'vendor/**/*',
|
50
|
+
]
|
51
|
+
|
52
|
+
|
53
|
+
spec = Gem::Specification.new do |s|
|
54
|
+
s.name = 'ap4r'
|
55
|
+
s.version = PKG_VERSION
|
56
|
+
s.summary = "Asynchronous Processing for Ruby."
|
57
|
+
s.description = <<-EOF
|
58
|
+
Asynchronous Processing for Ruby.
|
59
|
+
EOF
|
60
|
+
|
61
|
+
s.add_dependency(%q<reliable-msg>, ["= 1.1.0"])
|
62
|
+
|
19
63
|
s.has_rdoc = true
|
20
|
-
s.
|
21
|
-
s.
|
22
|
-
s.
|
64
|
+
s.extra_rdoc_files = ["README", "CHANGELOG", 'rails_plugin']
|
65
|
+
s.rdoc_options << "--main" << "README"
|
66
|
+
s.rdoc_options << "--title" << "Asynchronous Processing for Ruby"
|
67
|
+
s.rdoc_options << "--line-numbers"
|
68
|
+
|
69
|
+
|
70
|
+
s.files = PKG_FILES.to_a.delete_if {|f| f.include?('.svn')}
|
71
|
+
s.require_path = 'lib'
|
72
|
+
s.autorequire = %q{ap4r.rb}
|
73
|
+
|
74
|
+
s.bindir = "bin" # Use these for applications.
|
75
|
+
s.executables = ["ap4r_setup"]
|
76
|
+
s.default_executable = "ap4r_setup"
|
77
|
+
|
78
|
+
s.authors = ["Shunichi Shinohara", "Kiwamu Kato"]
|
79
|
+
s.email = %q{shinohara.shunichi@future.co.jp, kato.kiwamu@future.co.jp}
|
80
|
+
s.homepage = %q{http://rubyforge.org/projects/ap4r/}
|
81
|
+
s.rubyforge_project = "ap4r"
|
82
|
+
end
|
83
|
+
|
84
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
23
85
|
end
|
24
86
|
|
87
|
+
# Generate documentation ------------------------------------------------------------------
|
88
|
+
|
89
|
+
Rake::RDocTask.new { |rdoc|
|
90
|
+
rdoc.rdoc_dir = 'doc'
|
91
|
+
rdoc.options << '--line-numbers' << '--inline-source' << '--accessor' << 'cattr_accessor=rw'
|
92
|
+
rdoc.rdoc_files.include('README', 'CHANGELOG')
|
93
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
94
|
+
rdoc.rdoc_files.include('rails_plugin/**/*.rb')
|
95
|
+
}
|
96
|
+
|
97
|
+
# AP4R release ----------------------------------------------------------------
|
98
|
+
|
99
|
+
desc "Make gem and sample tgz"
|
100
|
+
task :release => [ :make_release_dir, :make_sample_tgz, :copy_to_release_dir ]
|
101
|
+
|
102
|
+
task :make_sample_tgz => [ :make_temp_dir, :copy_sample, :make_tgz ]
|
103
|
+
|
104
|
+
task :make_release_dir do
|
105
|
+
make_dir RELEASE_DIR
|
106
|
+
end
|
107
|
+
|
108
|
+
task :make_temp_dir do
|
109
|
+
make_dir TEMP_DIR
|
110
|
+
end
|
111
|
+
|
112
|
+
def make_dir(path)
|
113
|
+
if(File.exist?(path))
|
114
|
+
FileUtils.remove_entry(path, true)
|
115
|
+
end
|
116
|
+
FileUtils.mkdir_p(path)
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
task :copy_sample do
|
121
|
+
FileUtils.cp_r(HELLO_WORLD_DIR, TEMP_DIR)
|
122
|
+
Find.find(TEMP_DIR) {|f|
|
123
|
+
if f.include?('.svn')
|
124
|
+
FileUtils.rm_rf(f)
|
125
|
+
end
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
task :make_tgz do
|
130
|
+
Dir.chdir('temp/')
|
131
|
+
`tar czvf HelloWorld.tar.gz HelloWorld/`
|
132
|
+
Dir.chdir('../')
|
133
|
+
end
|
134
|
+
|
135
|
+
task :copy_to_release_dir do
|
136
|
+
Dir.foreach(PKG_DIR) {|f|
|
137
|
+
FileUtils.cp(PKG_DIR + '/' + f, RELEASE_DIR) if File.fnmatch("*.gem", f)
|
138
|
+
}
|
139
|
+
Dir.foreach(TEMP_DIR) {|f|
|
140
|
+
FileUtils.cp(TEMP_DIR + '/' + f, RELEASE_DIR) if File.fnmatch("*.tar.gz", f)
|
141
|
+
}
|
142
|
+
end
|
25
143
|
|
data/bin/ap4r_setup
ADDED
File without changes
|
File without changes
|