ap4r 0.1.0 → 0.1.1
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/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
|