ap4r 0.3.2 → 0.3.3

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.
@@ -6,6 +6,8 @@ require 'rubygems'
6
6
  require 'mongrel'
7
7
  require 'ap4r/mongrel'
8
8
 
9
+ Mongrel::Command::BANNER.gsub!("rails", "ap4r")
10
+
9
11
  module Ap4r::Mongrel
10
12
 
11
13
  module Command
@@ -17,6 +19,8 @@ module Ap4r::Mongrel
17
19
  klass.class_eval do |k|
18
20
  include(::Mongrel::Command::Base)
19
21
  end
22
+
23
+
20
24
  # TODO: Can subclass the return of RubyGems::GemPlugin ? 2007/04/16 by shino
21
25
  end
22
26
 
@@ -0,0 +1,13 @@
1
+ CREATE TABLE reliable_msg_queues (
2
+ id character varying(255) NOT NULL default '',
3
+ queue character varying(255) NOT NULL default '',
4
+ headers text NOT NULL,
5
+ object text NOT NULL,
6
+ PRIMARY KEY (id)
7
+ );
8
+ CREATE TABLE reliable_msg_topics (
9
+ topic character varying(255) NOT NULL default '',
10
+ headers text NOT NULL,
11
+ object text NOT NULL,
12
+ PRIMARY KEY (topic)
13
+ );
@@ -12,8 +12,8 @@ module ReliableMsg #:nodoc:
12
12
  class RetentionHistory
13
13
  include DRbUndumped
14
14
 
15
- LOOP_INTERVAL = 3.seconds
16
- SHELF_LIFE = 1.hour
15
+ LOOP_INTERVAL = 1.seconds
16
+ SHELF_LIFE = 10.minutes
17
17
  # SHELF_LIFE = 10.seconds
18
18
  attr_reader :data
19
19
 
@@ -9,7 +9,6 @@ begin
9
9
  require 'active_support'
10
10
  rescue LoadError
11
11
  require 'rubygems'
12
- gem 'active_support'
13
12
  require 'active_support'
14
13
  end
15
14
 
@@ -5,12 +5,12 @@
5
5
  begin
6
6
  require 'active_record'
7
7
  require 'uuid'
8
+ require 'reliable-msg'
8
9
  rescue LoadError
9
10
  require 'rubygems'
10
- gem 'activerecord'
11
11
  require 'activerecord'
12
- gem 'uuid'
13
12
  require 'uuid'
13
+ require 'reliable-msg'
14
14
  end
15
15
 
16
16
  module Ap4r
@@ -23,11 +23,30 @@ module Ap4r
23
23
 
24
24
  STATUS_STORED = 0
25
25
  STATUS_FORWARDED = 1
26
- STATUS_FAILED = -1
27
-
26
+ @@status_value_of = { :unforwarded => STATUS_STORED,
27
+ :forwarded => STATUS_FORWARDED }
28
+
28
29
  PHYSICAL = :physical
29
30
  LOGICAL = :logical
30
-
31
+
32
+ def dumped_headers
33
+ # The warning occurs when putting backslash into binaly type in PostgreSQL.
34
+ if "postgresql" == Ap4r::StoredMessage.establish_connection.config[:adapter]
35
+ self.headers
36
+ else
37
+ Marshal::dump(self.headers)
38
+ end
39
+ end
40
+
41
+ def dumped_object
42
+ # The warning occurs when putting backslash into binaly type in PostgreSQL.
43
+ if "postgresql" == Ap4r::StoredMessage.establish_connection.config[:adapter]
44
+ self.object
45
+ else
46
+ Marshal::dump(self.object)
47
+ end
48
+ end
49
+
31
50
  # Insert queue information, such as queue name and message, for next logic.
32
51
  #
33
52
  # duplication_check_id is generated from UUID and should be unique
@@ -42,8 +61,15 @@ module Ap4r
42
61
  s.duplication_check_id = UUID.new
43
62
  s.queue = queue_name
44
63
  s.status = STATUS_STORED
45
- s.object = Marshal::dump(queue_message)
46
- s.headers = Marshal::dump(rm_options)
64
+
65
+ # The warning occurs when putting backslash into binaly type in PostgreSQL.
66
+ if "postgresql" == Ap4r::StoredMessage.establish_connection.config[:adapter]
67
+ s.object = YAML.dump(queue_message)
68
+ s.headers = YAML.dump(rm_options)
69
+ else
70
+ s.object = Marshal::dump(queue_message)
71
+ s.headers = Marshal::dump(rm_options)
72
+ end
47
73
  end
48
74
 
49
75
  begin
@@ -86,5 +112,92 @@ module Ap4r
86
112
  self
87
113
  end
88
114
 
115
+ # List the records which have specified status.
116
+ # The statuses are :forwarded, :unforwarded and :all.
117
+ # :unforwarded means unprocessed or error during forward process.
118
+ def self.find_status_of(status = :unforwarded)
119
+ case status
120
+ when :all
121
+ StoredMessage.find(:all)
122
+ when :forwarded, :unforwarded
123
+ StoredMessage.find(:all, :conditions => { :status => @@status_value_of[status] })
124
+ else
125
+ puts "Undefined status: #{status.to_s}."
126
+ puts "Usage: Ap4r::StoredMessage.find_on [ :forwarded | :unforwarded | :all ]"
127
+ end
128
+ end
129
+
130
+ # Return id, queue_name and created date time.
131
+ def to_summary_string
132
+ return "#{self.id}, #{self.queue}, #{self.created_at}"
133
+ end
134
+
135
+ # Update status value.
136
+ def self.update_status(id, status)
137
+ return "undefined status: #{status}" unless @@status_value_of.keys.include? status
138
+ stored_message = StoredMessage.find(id)
139
+
140
+ before_status = stored_message.status
141
+ after_status = @@status_value_of[status]
142
+
143
+ stored_message.status = after_status
144
+ stored_message.save!
145
+ end
146
+
147
+ # Try to forward the ONE message which status is unforwarded.
148
+ # If the message is forwarded successfully, the status will be "1" that means forwarded.
149
+ def self.reforward(id)
150
+ stored_message = StoredMessage.find(id)
151
+ if stored_message.status == @@status_value_of[:forwarded]
152
+ raise "The message (id = #{id}) was already forwarded."
153
+ end
154
+ stored_message.forward_and_update_status
155
+ end
156
+
157
+ # Try to forward all messages which status are unforwarded.
158
+ # This method issue commit command to database every transaction_num.
159
+ def self.reforward_all(transaction_num = 10)
160
+
161
+ stored_messages = StoredMessage.find(:all,
162
+ :conditions => {:status => @@status_value_of[:unforwarded]})
163
+ total_num = stored_messages.size
164
+ failed_num = 0
165
+
166
+ 0.step(total_num, transaction_num) do |offset|
167
+ target_sms = stored_messages[offset..(offset + transaction_num - 1)]
168
+ next if target_sms.empty?
169
+ begin
170
+ StoredMessage.transaction do
171
+ target_sms.each do |target_sm|
172
+ target_sm.forward_and_update_status
173
+ end
174
+ end
175
+ rescue Exception => error
176
+ puts error.message
177
+ failed_num += target_sms.size
178
+ end
179
+ end
180
+ return [total_num - failed_num, failed_num]
181
+ end
182
+
183
+ def forward_and_update_status
184
+ queue_name = self.queue
185
+
186
+ # The warning occurs when putting backslash into binaly type in PostgreSQL.
187
+ if "postgresql" == Ap4r::StoredMessage.establish_connection.config[:adapter]
188
+ queue_headers = YAML.load(self.headers)
189
+ queue_messages = YAML.load(self.object)
190
+ else
191
+ queue_headers = Marshal::load(self.headers)
192
+ queue_messages = Marshal::load(self.object)
193
+ end
194
+
195
+ q = ::ReliableMsg::Queue.new(queue_name, :drb_uri => Ap4r::AsyncHelper::Base::DRUBY_URI)
196
+ q.put(queue_messages, queue_headers)
197
+
198
+ self.status = STATUS_FORWARDED
199
+ self.save!
200
+ end
201
+
89
202
  end
90
203
  end
data/lib/ap4r/version.rb CHANGED
@@ -8,7 +8,7 @@ module Ap4r
8
8
  module VERSION #:nodoc:
9
9
  MAJOR = 0
10
10
  MINOR = 3
11
- TINY = 2
11
+ TINY = 3
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY].join('.')
14
14
  end
@@ -0,0 +1,21 @@
1
+ # Author:: Kiwamu Kato
2
+ # Copyright:: Copyright (c) 2006 Future System Consulting Corp.
3
+ # Licence:: MIT Licence
4
+
5
+ class CreateTableForSaf < ActiveRecord::Migration
6
+ def self.up
7
+ create_table :stored_messages do |t|
8
+ t.column :duplication_check_id, :string, :null => false
9
+ t.column :queue, :string, :null => false
10
+ t.column :headers, :binary, :null => false
11
+ t.column :object, :binary, :null => false
12
+ t.column :status, :integer, :null => false
13
+ t.column :created_at, :datetime, :null => false
14
+ t.column :updated_at, :datetime, :null => false
15
+ end
16
+ end
17
+
18
+ def self.down
19
+ drop_table :stored_messages
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # Author:: Kiwamu Kato
2
+ # Copyright:: Copyright (c) 2006 Future System Consulting Corp.
3
+ # Licence:: MIT Licence
4
+
5
+ class CreateTableForSaf < ActiveRecord::Migration
6
+ def self.up
7
+ create_table :stored_messages do |t|
8
+ t.column :duplication_check_id, :string, :null => false
9
+ t.column :queue, :string, :null => false
10
+ t.column :headers, :text, :null => false
11
+ t.column :object, :text, :null => false
12
+ t.column :status, :integer, :null => false
13
+ t.column :created_at, :datetime, :null => false
14
+ t.column :updated_at, :datetime, :null => false
15
+ end
16
+ end
17
+
18
+ def self.down
19
+ drop_table :stored_messages
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ # Author:: Shunichi Shinohara
2
+ # Copyright:: Copyright (c) 2007 Future Architect Inc.
3
+ # Licence:: MIT Licence
4
+
5
+ require 'ap4r_client'
6
+
7
+ class ActionController::Base
8
+ def ap4r
9
+ @ap4r_client ||= ::Ap4r::Client.new(self)
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ # Author:: Shunichi Shinohara
2
+ # Copyright:: Copyright (c) 2007 Future Architect Inc.
3
+ # Licence:: MIT Licence
4
+
5
+ module Ap4r
6
+ module AsyncHelper
7
+ module Base
8
+ def queued_messages
9
+ return @queued_messages if @queued_messages
10
+ @queued_messages = Hash.new {|hash, key| hash[key] = []}
11
+ return @queued_messages
12
+ end
13
+
14
+ private
15
+ def __queue_put(queue_name, message, headers)
16
+ queued_messages[queue_name] << {:headers => headers, :body => message}
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,165 @@
1
+ # Author:: Shunichi Shinohara
2
+ # Copyright:: Copyright (c) 2007 Future Architect Inc.
3
+ # Licence:: MIT Licence
4
+
5
+ require 'rubygems'
6
+ require 'erb'
7
+ require 'yaml'
8
+ require 'reliable-msg'
9
+ require 'ap4r'
10
+ require 'timeout'
11
+
12
+ module Ap4r
13
+
14
+ class ServiceHandler
15
+
16
+ def initialize(config_file = RAILS_ROOT + "/config/test_async.yml")
17
+ raise "please create config/test_async.yml to configure ap4r service." unless File.exist?(config_file)
18
+
19
+ config = {}
20
+ File.open(config_file, "r") do |input|
21
+ YAML.load_documents(ERB.new(input.read).result) do |doc|
22
+ config.merge! doc
23
+ end
24
+ end
25
+ @test_config = config["ap4r"]
26
+ @root_dir = @test_config["root_dir"]
27
+ @config_file = @test_config["config_file"]
28
+ @test_server_config = ReliableMsg::Config.new(File.join(@root_dir, @config_file))
29
+ raise "config file #{@test_server_config.path} NOT exist!" unless @test_server_config.exist?
30
+
31
+ @test_server_config.load_no_create
32
+ @qm = nil
33
+ end
34
+
35
+ def qm
36
+ @qm ||= DRbObject.new_with_uri("druby://localhost:#{@test_server_config.drb["port"]}")
37
+ end
38
+
39
+ # Starts ap4r service.
40
+ def start_ap4r_service(wait_until_started = true)
41
+ command = "ruby #{@test_config["start_ruby_args"]} #{@root_dir}/script/mongrel_ap4r " +
42
+ "start -d -c #{@root_dir} -A #{@config_file} -p 13038"
43
+ message = "Starting Mongrel(AP4R)"
44
+ execute_command(command, message, false)
45
+ if wait_until_started
46
+ print "and waiting..."
47
+ wait_until_alive
48
+ end
49
+ puts "Done."
50
+ end
51
+
52
+ # Stops ap4r service.
53
+ def stop_ap4r_service
54
+ command = "ruby #{@test_config["stop_ruby_args"]} #{@root_dir}/script/mongrel_ap4r " +
55
+ "stop -c #{@root_dir}"
56
+ message = "Terminating Mongrel(AP4R)"
57
+ execute_command(command, message, false)
58
+ @qm = nil
59
+ end
60
+
61
+ # Starts rails service.
62
+ # Invokes mongrel_rails, so mongrel_rails should be installed.
63
+ def start_rails_service
64
+ # TODO: Can use script/server? It's more general. 2007/05/31 by shino
65
+ command = "mongrel_rails start -d --environment test"
66
+ message = "Starting Mongrel(Rails)"
67
+ execute_command(command, message)
68
+ end
69
+
70
+ # Stops rails service.
71
+ def stop_rails_service
72
+ # puts "read pid"
73
+ # pid = File.read('log/mongrel.pid').to_i
74
+ # puts "send signal to #{pid}"
75
+ # Process.kill(:TERM, `cat log/mongrel.pid`.to_i)
76
+ # puts "done"
77
+ # return
78
+ command = "mongrel_rails stop"
79
+ # command = "kill " + `cat log/mongrel.pid`
80
+ # command = "sh -c 'mongrel_rails stop'"
81
+ message = "Terminating Mongrel(Rails)"
82
+ execute_command(command, message, false)
83
+ end
84
+
85
+ # Starts rails service and ap4r service.
86
+ # After block execution, stops both.
87
+ def with_services
88
+ begin
89
+ start_rails_service
90
+ begin
91
+ start_ap4r_service
92
+ yield
93
+ ensure
94
+ stop_ap4r_service
95
+ end
96
+ ensure
97
+ stop_rails_service
98
+ end
99
+ end
100
+
101
+ def start_dispatchers
102
+ qm.dispatchers.start
103
+ end
104
+
105
+ def stop_dispatchers
106
+ qm.dispatchers.stop
107
+ end
108
+
109
+ def clear(*queues)
110
+ raise "not yet implemented"
111
+ queues.each do |queue|
112
+ q = ReliableMsg::Queue.new(queue)
113
+ loop do
114
+ break unless q.get
115
+ end
116
+ end
117
+ end
118
+
119
+ def wait_for_saf_forward
120
+ 50.times do
121
+ count = ::Ap4r::StoredMessage.count(:conditions => {:status => ::Ap4r::StoredMessage::STATUS_STORED})
122
+ break if count == 0
123
+ sleep 0.2
124
+ end
125
+ end
126
+
127
+ def wait_all_done
128
+ 50.times do
129
+ break if flag = qm.no_active_message?
130
+ sleep 0.2
131
+ end
132
+ end
133
+
134
+ def dlq
135
+ qm.list :queue => "$dlq"
136
+ end
137
+
138
+ private
139
+ def execute_command(command, message, with_done_message = true)
140
+ command += ";" # force to execute via shell
141
+ print "#{message} with command: #{command}..."
142
+ begin
143
+ timeout(10) do
144
+ result = system("#{command}")
145
+ # TODO: handle result 2007/08/29 by shino
146
+ puts "Done." if with_done_message
147
+ end
148
+ rescue TimeoutError
149
+ puts "!!! command timed out !!!"
150
+ end
151
+ end
152
+
153
+ def wait_until_alive(message = nil)
154
+ 50.times do
155
+ print message if message
156
+ begin
157
+ break if qm.alive?
158
+ rescue => e
159
+ # ignore
160
+ end
161
+ sleep 0.2
162
+ end
163
+ end
164
+ end
165
+ end