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
@@ -1,9 +1,9 @@
|
|
1
1
|
---
|
2
2
|
store:
|
3
|
-
username: orca
|
4
3
|
type: mysql
|
5
4
|
host: localhost
|
6
5
|
database: ap4r
|
6
|
+
username: ap4r
|
7
7
|
password: ap4r
|
8
8
|
drb:
|
9
9
|
host:
|
@@ -11,5 +11,9 @@ drb:
|
|
11
11
|
acl: allow 127.0.0.1 allow 10.0.0.0/8
|
12
12
|
dispatchers:
|
13
13
|
-
|
14
|
-
|
14
|
+
targets: queue.*
|
15
15
|
threads: 1
|
16
|
+
#carriers:
|
17
|
+
# -
|
18
|
+
# source_uri: druby://another.host.local:6438
|
19
|
+
# threads: 1
|
data/lib/ap4r.rb
CHANGED
@@ -1,17 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
if Gem::Version.correct?(ARGV[0][1..-2])
|
5
|
-
version = ARGV[0][1..-2]
|
6
|
-
ARGV.shift
|
7
|
-
end
|
8
|
-
end
|
1
|
+
# Author:: Shunichi Shinohara
|
2
|
+
# Copyright:: Copyright (c) 2006 Future System Consulting Corp.
|
3
|
+
# Licence:: MIT Licence
|
9
4
|
|
10
|
-
|
5
|
+
require 'rubygems'
|
6
|
+
require_gem 'reliable-msg'
|
11
7
|
|
12
8
|
hack = true
|
13
9
|
debug_hack = true
|
14
10
|
|
11
|
+
require 'ap4r/version'
|
12
|
+
|
15
13
|
if hack
|
16
14
|
require "ap4r/queue_manager_ext"
|
17
15
|
end
|
@@ -1,7 +1,14 @@
|
|
1
|
+
# Author:: Shunichi Shinohara
|
2
|
+
# Copyright:: Copyright (c) 2006 Future System Consulting Corp.
|
3
|
+
# Licence:: MIT Licence
|
4
|
+
|
1
5
|
module ReliableMsg
|
2
6
|
module MessageStore
|
3
7
|
class Base
|
4
8
|
|
9
|
+
cattr_accessor :use_mysql_extention
|
10
|
+
@@use_mysql_extention = true
|
11
|
+
|
5
12
|
def stale_queue targets
|
6
13
|
queue_names = targets.split(/[\s;]/).
|
7
14
|
select{|queue| !queue.empty? }.
|
@@ -25,5 +32,24 @@ module ReliableMsg
|
|
25
32
|
end
|
26
33
|
|
27
34
|
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
if ReliableMsg::MessageStore::Base.use_mysql_extention
|
40
|
+
class Mysql
|
41
|
+
alias original_query query
|
42
|
+
def query(q, &block)
|
43
|
+
maybe_result = original_query(q, &block)
|
44
|
+
puts "Mysql extention: query called by #{q}"
|
45
|
+
puts "Mysql#query returns #{maybe_result}(class: #{maybe_result.class})." if $DEBUG
|
46
|
+
return maybe_result unless block && maybe_result.kind_of?(Mysql::Result)
|
47
|
+
begin
|
48
|
+
puts "Mysql extention: about to yield result." if $DEBUG
|
49
|
+
block.call(maybe_result)
|
50
|
+
ensure
|
51
|
+
maybe_result.free
|
52
|
+
end
|
53
|
+
end
|
28
54
|
end
|
29
55
|
end
|
data/lib/ap4r/multi_queue.rb
CHANGED
@@ -1,10 +1,28 @@
|
|
1
|
+
# Author:: Shunichi Shinohara
|
2
|
+
# Copyright:: Copyright (c) 2006 Future System Consulting Corp.
|
3
|
+
# Licence:: MIT Licence
|
4
|
+
|
1
5
|
module ReliableMsg
|
6
|
+
# The +MultiQueue+ is a kind of clients.
|
7
|
+
# This offers two extentions to <tt>ReliableMsg::Queue</tt>
|
8
|
+
# 1. specify multiple target queues, by as comma-separated queue names.
|
9
|
+
# 1. specify prefix of a collection of queues by an asterisk at the end.
|
10
|
+
# Exapmles:
|
11
|
+
# * <tt>"a.b.c"</tt> targets single queue.
|
12
|
+
# * <tt>"a.b.c, x.y.z"</tt> targets two queues.
|
13
|
+
# * <tt>"a.b.*"</tt> targets a collection of queues such as "a.b.c", "a.b.d", etc.
|
14
|
+
# * <tt>"a.b.*, x.y.*"</tt> targets two collections.
|
2
15
|
class MultiQueue < Client
|
16
|
+
# Creates a new +MultiQueue+ with target queues specified by +multi_queue+.
|
17
|
+
# See <tt>ReliableMsg::Queue</tt> for +options+.
|
3
18
|
def initialize multi_queue, options = nil
|
4
19
|
@multi_queue = multi_queue
|
5
20
|
@options = options
|
6
21
|
end
|
7
22
|
|
23
|
+
# Gets a message from target queues.
|
24
|
+
# Internally, first search a queue with the most stale message,
|
25
|
+
# and get a message from the queue by <tt>ReliableMsg::Queue#get</tt>
|
8
26
|
def get selector = nil, &block
|
9
27
|
queue_name = repeated {|qm|
|
10
28
|
qm.stale_queue @multi_queue
|
@@ -14,6 +32,7 @@ module ReliableMsg
|
|
14
32
|
queue.get selector, &block
|
15
33
|
end
|
16
34
|
|
35
|
+
# Returns multi queue expression as +String+.
|
17
36
|
def name
|
18
37
|
@multi_queue
|
19
38
|
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# Author:: Shunichi Shinohara
|
2
|
+
# Copyright:: Copyright (c) 2006 Future System Consulting Corp.
|
3
|
+
# Licence:: MIT Licence
|
4
|
+
|
1
5
|
require 'ap4r/message_store_ext'
|
2
6
|
require 'ap4r/multi_queue'
|
3
7
|
require 'ap4r/retention_history'
|
@@ -11,11 +15,13 @@ require 'thread'
|
|
11
15
|
require 'pp'
|
12
16
|
|
13
17
|
module ReliableMsg
|
14
|
-
module LifecycleListener
|
18
|
+
module LifecycleListener #:nodoc:
|
15
19
|
|
16
20
|
end
|
17
21
|
|
18
22
|
class QueueManager
|
23
|
+
# Gets a queue name which has the most stale message
|
24
|
+
# in queues specified by +multi_queue+.
|
19
25
|
def stale_queue multi_queue
|
20
26
|
@store.stale_queue multi_queue
|
21
27
|
end
|
@@ -24,7 +30,11 @@ module ReliableMsg
|
|
24
30
|
alias :stop_original :stop
|
25
31
|
alias :initialize_original :initialize
|
26
32
|
|
27
|
-
|
33
|
+
# Hooks original initialize method to add lifecyle listeners.
|
34
|
+
#--
|
35
|
+
# TODO: Make dispatchers and carriers lifecyle listeners
|
36
|
+
# and separate them from QueueManager.
|
37
|
+
def initialize options = nil #:notnew:
|
28
38
|
initialize_original options
|
29
39
|
@global_lock ||= Mutex.new
|
30
40
|
@lifecycle_listeners = []
|
@@ -59,8 +69,8 @@ module ReliableMsg
|
|
59
69
|
end
|
60
70
|
|
61
71
|
def start_dispatchers
|
62
|
-
return unless @config.
|
63
|
-
@logger.info{ "about to start dispatchers with config #{@config.
|
72
|
+
return unless @config.dispatchers
|
73
|
+
@logger.info{ "about to start dispatchers with config #{@config.dispatchers.to_yaml}" }
|
64
74
|
@disps = ThreadGroup.new
|
65
75
|
@config.dispatchers.each{ |conf|
|
66
76
|
conf["threads"].to_i.times { |index|
|
@@ -74,6 +84,8 @@ module ReliableMsg
|
|
74
84
|
begin
|
75
85
|
mq.get{|m|
|
76
86
|
logger.debug{"dispatcher get message\n#{m.to_yaml}"} if m
|
87
|
+
# TODO: divede into comcrete classes by protocols.
|
88
|
+
|
77
89
|
# version 1 SOAP
|
78
90
|
# driver = SOAP::WSDLDriverFactory.new(m[:target_url]).create_rpc_driver
|
79
91
|
# logger.debug(driver)
|
@@ -135,6 +147,8 @@ module ReliableMsg
|
|
135
147
|
end
|
136
148
|
#logger.debug{ "carrier gets a message\n#{m.to_yaml}" }
|
137
149
|
|
150
|
+
# TODO: decide the better one, and delete another.
|
151
|
+
|
138
152
|
#version 1: use thread fork so queue manager use a different tx
|
139
153
|
# TODO probably should have a thread as an instance variable or in a thread local
|
140
154
|
#Thread.fork(m) {|m|
|
@@ -1,9 +1,22 @@
|
|
1
|
+
# Author:: Shunichi Shinohara
|
2
|
+
# Copyright:: Copyright (c) 2006 Future System Consulting Corp.
|
3
|
+
# Licence:: MIT Licence
|
4
|
+
|
1
5
|
require 'drb/drb'
|
2
6
|
|
3
7
|
module ReliableMsg
|
4
8
|
class QueueManager
|
5
9
|
attr_reader :store, :transactions, :mutex, :config
|
6
10
|
|
11
|
+
# Accepts ruby code as a string, evaluates it on +self+,
|
12
|
+
# and returns the result as a formatted string.
|
13
|
+
# Formats can be one of followings.
|
14
|
+
# * <tt>:inspect</tt> : default value
|
15
|
+
# * <tt>:yaml</tt>
|
16
|
+
# * <tt>:json</tt>
|
17
|
+
# * <tt>:xml</tt>
|
18
|
+
# Apart from <tt>:inspect</tt>, format can fail depending on
|
19
|
+
# the result object.
|
7
20
|
def eval_to_inspect code, inspect_mode = :inspect
|
8
21
|
# TODO: too sloppy implementation
|
9
22
|
result = Thread.new(code, inspect_mode){ |c, mode|
|
@@ -1,6 +1,13 @@
|
|
1
|
+
# Author:: Shunichi Shinohara
|
2
|
+
# Copyright:: Copyright (c) 2006 Future System Consulting Corp.
|
3
|
+
# Licence:: MIT Licence
|
4
|
+
|
1
5
|
require 'active_support'
|
2
6
|
|
3
7
|
module ReliableMsg
|
8
|
+
# This class is too much experimental.
|
9
|
+
# The aim: for performance monitoring, records unprocessed message count
|
10
|
+
# in every queues at some interval.
|
4
11
|
class RetentionHistory
|
5
12
|
include DRbUndumped
|
6
13
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Author:: Shunichi Shinohara
|
2
|
+
# Copyright:: Copyright (c) 2006 Future System Consulting Corp.
|
3
|
+
# Licence:: MIT Licence
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'ap4r'
|
7
|
+
|
8
|
+
module AP4R
|
9
|
+
module Script
|
10
|
+
class QueueManagerControl < Base
|
11
|
+
def start argv, options = {}
|
12
|
+
ARGV.unshift('manager', 'start')
|
13
|
+
run_rm_client
|
14
|
+
end
|
15
|
+
|
16
|
+
def stop argv, options = {}
|
17
|
+
ARGV.unshift('manager', 'stop')
|
18
|
+
run_rm_client
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def run_rm_client
|
23
|
+
ReliableMsg::CLI.new.run
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Author:: Shunichi Shinohara
|
2
|
+
# Copyright:: Copyright (c) 2006 Future System Consulting Corp.
|
3
|
+
# Licence:: MIT Licence
|
4
|
+
|
5
|
+
$:.unshift(File.join(File.dirname(__FILE__), '../../'))
|
6
|
+
|
7
|
+
require 'logger'
|
8
|
+
begin
|
9
|
+
require 'active_support'
|
10
|
+
rescue LoadError
|
11
|
+
require 'rubygems'
|
12
|
+
require_gem 'active_support'
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'ap4r/script/base'
|
16
|
+
AP4R::Script::Base.logger = Logger.new(STDOUT)
|
17
|
+
AP4R::Script::Base.ap4r_base = File.join(File.dirname(__FILE__) , '../../../')
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Author:: Shunichi Shinohara
|
2
|
+
# Copyright:: Copyright (c) 2006 Future System Consulting Corp.
|
3
|
+
# Licence:: MIT Licence
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
module AP4R
|
9
|
+
module Script
|
10
|
+
class WorkspaceGenerator < Base
|
11
|
+
AP4R_Directories = %w(config log script tmp)
|
12
|
+
|
13
|
+
def run argv, options
|
14
|
+
OptionParser.new {|opt|
|
15
|
+
opt.on('-m'){
|
16
|
+
# merge to rails project but not implemented yet...
|
17
|
+
}
|
18
|
+
|
19
|
+
opt.parse!(argv)
|
20
|
+
}
|
21
|
+
|
22
|
+
dir = argv.last
|
23
|
+
unless dir
|
24
|
+
logger.warn{"Specify a name of application root directory."}
|
25
|
+
exit(1)
|
26
|
+
end
|
27
|
+
|
28
|
+
root_dir = File.expand_path(dir)
|
29
|
+
|
30
|
+
logger.info{"make application root directory [#{root_dir}] ... "}
|
31
|
+
FileUtils.mkdir_p(root_dir)
|
32
|
+
|
33
|
+
logger.info{"make directories for AP4R [#{AP4R_Directories.join(", ")}] ..."}
|
34
|
+
FileUtils.mkdir_p(AP4R_Directories.map{|d| File.join(root_dir, d)})
|
35
|
+
|
36
|
+
%w(config script).each{ |recursive_copy_dir|
|
37
|
+
copy_files(File.join(ap4r_base, recursive_copy_dir),
|
38
|
+
File.join(root_dir, recursive_copy_dir))
|
39
|
+
}
|
40
|
+
|
41
|
+
logger.info{"\n[#{root_dir}] has successfully set up!\n"}
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
def copy_files(src_dir, dest_dir, excludes = /^\.|~$/, recursive = true)
|
47
|
+
logger.info{"copy files from #{File.expand_path(src_dir)} to #{dest_dir} ..."}
|
48
|
+
Dir.foreach(src_dir) {|name|
|
49
|
+
next if name =~ excludes
|
50
|
+
path = File.join(src_dir, name)
|
51
|
+
FileUtils.cp(path, dest_dir) if FileTest.file?(path)
|
52
|
+
|
53
|
+
if recursive && FileTest.directory?(path)
|
54
|
+
next_dest_dir = File.join(dest_dir, name)
|
55
|
+
FileUtils.mkdir_p(next_dest_dir)
|
56
|
+
copy_files(path, next_dest_dir, excludes, recursive)
|
57
|
+
end
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# Author:: Shunichi Shinohara
|
2
|
+
# Copyright:: Copyright (c) 2006 Future System Consulting Corp.
|
3
|
+
# Licence:: MIT Licence
|
4
|
+
|
5
|
+
$KCODE = 'u'
|
6
|
+
|
7
|
+
require 'singleton'
|
8
|
+
require 'rubygems'
|
9
|
+
require 'ap4r'
|
10
|
+
require 'ap4r/util/queue_client'
|
11
|
+
|
12
|
+
class AP4R::Configuration #:nodoc:
|
13
|
+
SETTINGS_FILES_DEFAULT = %w( config/ap4r_settings.rb )
|
14
|
+
|
15
|
+
class Services #:nodoc:
|
16
|
+
include Singleton
|
17
|
+
include Enumerable
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@list = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def add(*args)
|
24
|
+
client = AP4R::Util::QueueClient.new(*args)
|
25
|
+
@list << (client)
|
26
|
+
end
|
27
|
+
|
28
|
+
def each(&block)
|
29
|
+
@list.each(&block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def setup
|
35
|
+
yield Services.instance
|
36
|
+
end
|
37
|
+
|
38
|
+
def services
|
39
|
+
Services.instance
|
40
|
+
end
|
41
|
+
|
42
|
+
def load_setting_files(settings_files = SETTINGS_FILES_DEFAULT)
|
43
|
+
settings_files.each{ |file|
|
44
|
+
load(file) if FileTest.file?(file)
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
# This class is TOO MUCH EXPERIMENTAL.
|
52
|
+
#
|
53
|
+
# IRM is the interactive reliable-msg shell.
|
54
|
+
class IRM
|
55
|
+
class << self
|
56
|
+
def [](name)
|
57
|
+
sym_name = name.to_sym
|
58
|
+
AP4R::Configuration.services.find{|service| service.name == sym_name }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
#--
|
64
|
+
|
65
|
+
def each(&block)
|
66
|
+
AP4R::Configuration.services.each(&block)
|
67
|
+
end
|
68
|
+
extend Enumerable
|
69
|
+
|
70
|
+
AP4R::Configuration.load_setting_files
|
71
|
+
|
72
|
+
$original_main = self
|
73
|
+
|
74
|
+
class Object
|
75
|
+
AP4R::Configuration.services.each {|s|
|
76
|
+
module_eval <<-EOS
|
77
|
+
def #{s.name.to_s}
|
78
|
+
irb_change_workspace(IRM[:#{s.name.to_s}])
|
79
|
+
end
|
80
|
+
EOS
|
81
|
+
}
|
82
|
+
|
83
|
+
def main
|
84
|
+
irb_change_workspace($original_main)
|
85
|
+
nil
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
require 'irb'
|
91
|
+
IRB.start
|
92
|
+
|
93
|
+
#++
|