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
@@ -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
|
+
#++
|