backgroundrb-rails3 1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +17 -0
- data/ChangeLog +50 -0
- data/Gemfile +11 -0
- data/LICENSE +4 -0
- data/MIT-LICENSE +20 -0
- data/README +22 -0
- data/Rakefile +128 -0
- data/TODO.org +5 -0
- data/app/controller/backgroundrb_status_controller.rb +6 -0
- data/backgroundrb-rails3.gemspec +219 -0
- data/config/backgroundrb.yml +11 -0
- data/doc/Rakefile +5 -0
- data/doc/config.yaml +2 -0
- data/doc/content/advanced/advanced.txt +76 -0
- data/doc/content/advanced/advanced.yaml +4 -0
- data/doc/content/bugs/bugs.txt +20 -0
- data/doc/content/bugs/bugs.yaml +5 -0
- data/doc/content/community/community.txt +36 -0
- data/doc/content/community/community.yaml +5 -0
- data/doc/content/content.txt +168 -0
- data/doc/content/content.yaml +5 -0
- data/doc/content/faq/faq.txt +41 -0
- data/doc/content/faq/faq.yaml +5 -0
- data/doc/content/rails/rails.txt +182 -0
- data/doc/content/rails/rails.yaml +5 -0
- data/doc/content/scheduling/scheduling.txt +166 -0
- data/doc/content/scheduling/scheduling.yaml +5 -0
- data/doc/content/workers/workers.txt +178 -0
- data/doc/content/workers/workers.yaml +5 -0
- data/doc/layouts/default/default.erb +56 -0
- data/doc/layouts/default/default.yaml +4 -0
- data/doc/lib/default.rb +7 -0
- data/doc/output/Assets/BG-Ad-Top.png +0 -0
- data/doc/output/Assets/BG-Body.png +0 -0
- data/doc/output/Assets/BG-Feed.png +0 -0
- data/doc/output/Assets/BG-Menu-Hover.png +0 -0
- data/doc/output/Assets/BG-Menu.png +0 -0
- data/doc/output/Assets/BG-Sidebar-Bottom.png +0 -0
- data/doc/output/Assets/Button-Feed.png +0 -0
- data/doc/output/images/bg-ad-top.png +0 -0
- data/doc/output/images/bg-body.png +0 -0
- data/doc/output/images/bg-feed.gif +0 -0
- data/doc/output/images/bg-footer.jpg +0 -0
- data/doc/output/images/bg-header.jpg +0 -0
- data/doc/output/images/bg-menu-hover.png +0 -0
- data/doc/output/images/bg-menu.png +0 -0
- data/doc/output/images/bg-sidebar-bottom.gif +0 -0
- data/doc/output/images/button-feed.png +0 -0
- data/doc/output/images/icon-comment.png +0 -0
- data/doc/output/images/more_icon.gif +0 -0
- data/doc/output/style.css +299 -0
- data/doc/page_defaults.yaml +13 -0
- data/doc/tasks/default.rake +3 -0
- data/doc/templates/default/default.txt +1 -0
- data/doc/templates/default/default.yaml +4 -0
- data/examples/backgroundrb.yml +25 -0
- data/examples/foo_controller.rb +48 -0
- data/examples/god_worker.rb +7 -0
- data/examples/worker_tests/god_worker_test.rb +8 -0
- data/examples/workers/error_worker.rb +17 -0
- data/examples/workers/foo_worker.rb +38 -0
- data/examples/workers/god_worker.rb +7 -0
- data/examples/workers/model_worker.rb +13 -0
- data/examples/workers/renewal_worker.rb +11 -0
- data/examples/workers/rss_worker.rb +26 -0
- data/examples/workers/server_worker.rb +31 -0
- data/examples/workers/world_worker.rb +12 -0
- data/examples/workers/xmpp_worker.rb +7 -0
- data/init.rb +7 -0
- data/install.rb +1 -0
- data/know_issues.org +5 -0
- data/lib/backgroundrb.rb +1 -0
- data/lib/backgroundrb/bdrb_client_helper.rb +8 -0
- data/lib/backgroundrb/bdrb_cluster_connection.rb +156 -0
- data/lib/backgroundrb/bdrb_config.rb +43 -0
- data/lib/backgroundrb/bdrb_conn_error.rb +29 -0
- data/lib/backgroundrb/bdrb_connection.rb +179 -0
- data/lib/backgroundrb/bdrb_job_queue.rb +79 -0
- data/lib/backgroundrb/bdrb_result.rb +19 -0
- data/lib/backgroundrb/bdrb_start_stop.rb +146 -0
- data/lib/backgroundrb/rails_worker_proxy.rb +181 -0
- data/lib/backgroundrb/railtie.rb +48 -0
- data/lib/generators/backgroundrb/bdrb_migration/USAGE +12 -0
- data/lib/generators/backgroundrb/bdrb_migration/bdrb_migration_generator.rb +15 -0
- data/lib/generators/backgroundrb/bdrb_migration/templates/migration.rb +27 -0
- data/lib/generators/backgroundrb/worker/USAGE +16 -0
- data/lib/generators/backgroundrb/worker/templates/unit_test.rb +12 -0
- data/lib/generators/backgroundrb/worker/templates/worker.rb +7 -0
- data/lib/generators/backgroundrb/worker/worker_generator.rb +14 -0
- data/lib/tasks/backgroundrb_tasks.rake +103 -0
- data/release_notes.org +48 -0
- data/release_points.org +46 -0
- data/script/backgroundrb +52 -0
- data/script/bdrb_test_helper.rb +99 -0
- data/script/load_worker_env.rb +31 -0
- data/script/monitrc +25 -0
- data/server/backgroundrb_server.rb +12 -0
- data/server/lib/bdrb_result_storage.rb +62 -0
- data/server/lib/bdrb_server_helper.rb +24 -0
- data/server/lib/bdrb_thread_pool.rb +127 -0
- data/server/lib/cron_trigger.rb +197 -0
- data/server/lib/invalid_dump_error.rb +4 -0
- data/server/lib/log_worker.rb +25 -0
- data/server/lib/master_proxy.rb +140 -0
- data/server/lib/master_worker.rb +187 -0
- data/server/lib/meta_worker.rb +432 -0
- data/server/lib/trigger.rb +34 -0
- data/test/bdrb_client_test_helper.rb +5 -0
- data/test/bdrb_test_helper.rb +35 -0
- data/test/client/backgroundrb.yml +17 -0
- data/test/client/test_bdrb_client_helper.rb +13 -0
- data/test/client/test_bdrb_cluster_connection.rb +162 -0
- data/test/client/test_bdrb_config.rb +20 -0
- data/test/client/test_bdrb_connection.rb +29 -0
- data/test/client/test_bdrb_job_queue.rb +63 -0
- data/test/client/test_worker_proxy.rb +130 -0
- data/test/server/test_cron_trigger.rb +281 -0
- data/test/server/test_master_proxy.rb +54 -0
- data/test/server/test_master_worker.rb +157 -0
- data/test/server/test_meta_worker.rb +281 -0
- data/test/server/test_result_storage.rb +14 -0
- data/test/socket_mocker.rb +34 -0
- data/test/workers/bar_worker.rb +10 -0
- data/test/workers/foo_worker.rb +10 -0
- data/uninstall.rb +1 -0
- metadata +345 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
# Put your code that runs your task inside the do_work method it will be
|
2
|
+
# run automatically in a thread. You have access to all of your rails
|
3
|
+
# models. You also get logger and results method inside of this class
|
4
|
+
# by default.
|
5
|
+
class ErrorWorker < BackgrounDRb::MetaWorker
|
6
|
+
set_worker_name :error_worker
|
7
|
+
set_no_auto_load(true)
|
8
|
+
|
9
|
+
def create(args = nil)
|
10
|
+
logger.info "creating error worker"
|
11
|
+
end
|
12
|
+
|
13
|
+
def hello_world(data)
|
14
|
+
logger.info "invoking #{worker_name} hello world #{data} #{Time.now}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Put your code that runs your task inside the do_work method it will be
|
2
|
+
# run automatically in a thread. You have access to all of your rails
|
3
|
+
# models. You also get logger and results method inside of this class
|
4
|
+
# by default.
|
5
|
+
|
6
|
+
class TimeClient
|
7
|
+
def receive_data(p_data)
|
8
|
+
worker.get_external_data(p_data)
|
9
|
+
end
|
10
|
+
|
11
|
+
def post_init
|
12
|
+
p "***************** : connection completed"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class FooWorker < BackgrounDRb::MetaWorker
|
17
|
+
set_worker_name :foo_worker
|
18
|
+
def create(args = nil)
|
19
|
+
#register_status("Running")
|
20
|
+
add_periodic_timer(10) { foobar }
|
21
|
+
external_connection = nil
|
22
|
+
connect("localhost",11009,TimeClient) { |conn| external_connection = conn }
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_external_data(p_data)
|
26
|
+
cache[some_key] = p_data
|
27
|
+
end
|
28
|
+
|
29
|
+
def foobar
|
30
|
+
cache[some_key] = "Time is now : #{Time.now}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def barbar(data)
|
34
|
+
logger.info "invoking babrbar on #{Time.now} #{data}"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class ModelWorker < BackgrounDRb::MetaWorker
|
2
|
+
set_worker_name :model_worker
|
3
|
+
def create(args = nil)
|
4
|
+
#add_periodic_timer(2) { add_new_user }
|
5
|
+
end
|
6
|
+
|
7
|
+
def add_new_user
|
8
|
+
login,age = "Hemant: #{Time.now}",rand(24)
|
9
|
+
logger.info "creating user #{login} with age #{age}"
|
10
|
+
User.create(:login => login, :age => age)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# this worker would test thread issues that were discussed before
|
2
|
+
require "net/http"
|
3
|
+
class RssWorker < BackgrounDRb::MetaWorker
|
4
|
+
set_worker_name :rss_worker
|
5
|
+
def create(args = nil)
|
6
|
+
# this method is called, when worker is loaded for the first time
|
7
|
+
end
|
8
|
+
|
9
|
+
# method would fetch supplied urls in a thread
|
10
|
+
def fetch_url(url)
|
11
|
+
puts "fetching url #{url}"
|
12
|
+
thread_pool.defer(:scrap_things,url)
|
13
|
+
end
|
14
|
+
|
15
|
+
def scrap_things url
|
16
|
+
begin
|
17
|
+
data = Net::HTTP.get(url,"/")
|
18
|
+
File.open("#{RAILS_ROOT}/log/pages.txt","w") do |fl|
|
19
|
+
fl.puts(data)
|
20
|
+
end
|
21
|
+
rescue
|
22
|
+
logger.info "Error downloading page"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class TimeServer
|
2
|
+
# the data send by client would be received here
|
3
|
+
def receive_data(p_data)
|
4
|
+
end
|
5
|
+
|
6
|
+
# would be called when someone connects to the server for the
|
7
|
+
# first time
|
8
|
+
def post_init
|
9
|
+
add_periodic_timer(2) { say_hello_world }
|
10
|
+
end
|
11
|
+
|
12
|
+
# would be called when client connection is complete.
|
13
|
+
def connection_completed
|
14
|
+
end
|
15
|
+
|
16
|
+
def say_hello_world
|
17
|
+
send_data("Hello World\n")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# this worker is going to act like server.
|
22
|
+
class ServerWorker < BackgrounDRb::MetaWorker
|
23
|
+
set_worker_name :server_worker
|
24
|
+
def create(args = nil)
|
25
|
+
# start the server when worker starts
|
26
|
+
start_server("0.0.0.0",11009,TimeServer) do |client_connection|
|
27
|
+
client_connection.say_hello_world
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
data/init.rb
ADDED
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Install hook code here
|
data/know_issues.org
ADDED
data/lib/backgroundrb.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "backgroundrb/railtie"
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# class stores connections to BackgrounDRb servers in a cluster manner
|
2
|
+
module BackgrounDRb
|
3
|
+
class ClusterConnection
|
4
|
+
include ClientHelper
|
5
|
+
attr_accessor :backend_connections,:config,:cache,:bdrb_servers
|
6
|
+
attr_accessor :disconnected_connections
|
7
|
+
|
8
|
+
# initialize cluster connection
|
9
|
+
def initialize
|
10
|
+
@bdrb_servers = []
|
11
|
+
@backend_connections = []
|
12
|
+
@disconnected_connections = {}
|
13
|
+
|
14
|
+
@last_polled_time = Time.now
|
15
|
+
@request_count = 0
|
16
|
+
|
17
|
+
initialize_memcache if BackgrounDRb::BDRB_CONFIG[:backgroundrb][:result_storage] == 'memcache'
|
18
|
+
establish_connections
|
19
|
+
@round_robin = (0...@backend_connections.length).to_a
|
20
|
+
end
|
21
|
+
|
22
|
+
# initialize memache if client is storing results in memcache
|
23
|
+
def initialize_memcache
|
24
|
+
require 'memcache'
|
25
|
+
memcache_options = {
|
26
|
+
:c_threshold => 10_000,
|
27
|
+
:compression => true,
|
28
|
+
:debug => false,
|
29
|
+
:namespace => 'backgroundrb_result_hash',
|
30
|
+
:readonly => false,
|
31
|
+
:urlencode => false
|
32
|
+
}
|
33
|
+
@cache = MemCache.new(memcache_options)
|
34
|
+
@cache.servers = BackgrounDRb::BDRB_CONFIG[:memcache].split(',')
|
35
|
+
end
|
36
|
+
|
37
|
+
# initialize all backend server connections
|
38
|
+
def establish_connections
|
39
|
+
klass = Struct.new(:ip,:port)
|
40
|
+
if t_servers = BackgrounDRb::BDRB_CONFIG[:client]
|
41
|
+
connections = t_servers.split(',')
|
42
|
+
connections.each do |conn_string|
|
43
|
+
ip = conn_string.split(':')[0]
|
44
|
+
port = conn_string.split(':')[1].to_i
|
45
|
+
@bdrb_servers << klass.new(ip,port)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
@bdrb_servers << klass.new(BackgrounDRb::BDRB_CONFIG[:backgroundrb][:ip],BackgrounDRb::BDRB_CONFIG[:backgroundrb][:port].to_i)
|
49
|
+
@bdrb_servers.each_with_index do |connection_info,index|
|
50
|
+
next if @backend_connections.detect { |x| x.server_info == "#{connection_info.ip}:#{connection_info.port}" }
|
51
|
+
@backend_connections << Connection.new(connection_info.ip,connection_info.port,self)
|
52
|
+
end
|
53
|
+
end # end of method establish_connections
|
54
|
+
|
55
|
+
# every 10 request or 10 seconds it will try to reconnect to bdrb servers which were down
|
56
|
+
def discover_server_periodically
|
57
|
+
@disconnected_connections.each do |key,connection|
|
58
|
+
connection.establish_connection
|
59
|
+
if connection.connection_status
|
60
|
+
@backend_connections << connection
|
61
|
+
connection.close_connection
|
62
|
+
@disconnected_connections[key] = nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
@disconnected_connections.delete_if { |key,value| value.nil? }
|
66
|
+
@round_robin = (0...@backend_connections.length).to_a
|
67
|
+
end
|
68
|
+
|
69
|
+
# Find live connections except those mentioned in array, because they
|
70
|
+
# are already dead.
|
71
|
+
def find_next_except_these connections
|
72
|
+
invalid_connections = @backend_connections.select { |x| connections.include?(x.server_info) }
|
73
|
+
@backend_connections.delete_if { |x| connections.include?(x.server_info) }
|
74
|
+
@round_robin = (0...@backend_connections.length).to_a
|
75
|
+
invalid_connections.each do |x|
|
76
|
+
@disconnected_connections[x.server_info] = x
|
77
|
+
end
|
78
|
+
chosen = @backend_connections.detect { |x| !(connections.include?(x.server_info)) }
|
79
|
+
raise NoServerAvailable.new("No BackgrounDRb server is found running") unless chosen
|
80
|
+
chosen
|
81
|
+
end
|
82
|
+
|
83
|
+
# Fina a connection by host name and port
|
84
|
+
def find_connection host_info
|
85
|
+
conn = @backend_connections.detect { |x| x.server_info == host_info }
|
86
|
+
raise NoServerAvailable.new("BackgrounDRb server is not found running on #{host_info}") unless conn
|
87
|
+
return conn
|
88
|
+
end
|
89
|
+
|
90
|
+
# find the local configured connection
|
91
|
+
def find_local
|
92
|
+
find_connection("#{BackgrounDRb::BDRB_CONFIG[:backgroundrb][:ip]}:#{BackgrounDRb::BDRB_CONFIG[:backgroundrb][:port]}")
|
93
|
+
end
|
94
|
+
|
95
|
+
# return the worker proxy
|
96
|
+
def worker(worker_name,worker_key = nil)
|
97
|
+
update_stats
|
98
|
+
RailsWorkerProxy.new(worker_name,worker_key,self)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Update the stats and discover new nodes if they came up.
|
102
|
+
def update_stats
|
103
|
+
@request_count += 1
|
104
|
+
discover_server_periodically if(time_to_discover? && !@disconnected_connections.empty?)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Check if, we should try to discover new bdrb servers
|
108
|
+
def time_to_discover?
|
109
|
+
if((@request_count%10 == 0) or (Time.now > (@last_polled_time + 10.seconds)))
|
110
|
+
@last_polled_time = Time.now
|
111
|
+
return true
|
112
|
+
else
|
113
|
+
return false
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Send worker information of all currently running workers from all configured bdrb
|
118
|
+
# servers
|
119
|
+
def all_worker_info
|
120
|
+
update_stats
|
121
|
+
info_data = {}
|
122
|
+
@backend_connections.each do |t_connection|
|
123
|
+
info_data[t_connection.server_info] = t_connection.all_worker_info rescue nil
|
124
|
+
end
|
125
|
+
return info_data
|
126
|
+
end
|
127
|
+
|
128
|
+
# one of the backend connections are chosen and worker is started on it
|
129
|
+
def new_worker(options = {})
|
130
|
+
update_stats
|
131
|
+
succeeded = false
|
132
|
+
result = nil
|
133
|
+
|
134
|
+
@backend_connections.each do |connection|
|
135
|
+
begin
|
136
|
+
result = connection.new_worker(options)
|
137
|
+
succeeded = true
|
138
|
+
rescue BdrbConnError; end
|
139
|
+
end
|
140
|
+
raise NoServerAvailable.new("No BackgrounDRb server is found running") unless succeeded
|
141
|
+
return options[:worker_key]
|
142
|
+
end
|
143
|
+
|
144
|
+
# choose a server in round robin manner.
|
145
|
+
def choose_server
|
146
|
+
if @round_robin.empty?
|
147
|
+
@round_robin = (0...@backend_connections.length).to_a
|
148
|
+
end
|
149
|
+
if @round_robin.empty? && @backend_connections.empty?
|
150
|
+
discover_server_periodically
|
151
|
+
raise NoServerAvailable.new("No BackgrounDRb server is found running") if @round_robin.empty? && @backend_connections.empty?
|
152
|
+
end
|
153
|
+
@backend_connections[@round_robin.shift]
|
154
|
+
end
|
155
|
+
end # end of ClusterConnection
|
156
|
+
end # end of Module BackgrounDRb
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'erb'
|
3
|
+
module BackgrounDRb
|
4
|
+
class Config
|
5
|
+
def self.parse_cmd_options(argv)
|
6
|
+
options = { }
|
7
|
+
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
script_name = File.basename($0)
|
10
|
+
opts.banner = "Usage: #{$0} [options]"
|
11
|
+
opts.separator ""
|
12
|
+
opts.on("-e", "--environment=name", String,
|
13
|
+
"Specifies the environment to operate under (test/development/production).",
|
14
|
+
"Default: development") { |v| options[:environment] = v }
|
15
|
+
opts.separator ""
|
16
|
+
opts.on("-h", "--help",
|
17
|
+
"Show this help message.") { $stderr.puts opts; exit }
|
18
|
+
opts.separator ""
|
19
|
+
opts.on("-v","--version",
|
20
|
+
"Show version.") { $stderr.puts "1.1"; exit }
|
21
|
+
end.parse!(argv)
|
22
|
+
|
23
|
+
ENV["RAILS_ENV"] = options[:environment] if options[:environment]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.read_config(config_file)
|
27
|
+
config = YAML.load(ERB.new(IO.read(config_file)).result)
|
28
|
+
environment = ENV["RAILS_ENV"] || config[:backgroundrb][:environment] || "development"
|
29
|
+
|
30
|
+
if respond_to?(:silence_warnings)
|
31
|
+
silence_warnings do
|
32
|
+
Object.const_set("RAILS_ENV",environment)
|
33
|
+
end
|
34
|
+
else
|
35
|
+
Object.const_set("RAILS_ENV",environment)
|
36
|
+
end
|
37
|
+
|
38
|
+
ENV["RAILS_ENV"] = environment
|
39
|
+
config
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Exception class for BackgrounDRb connection errors
|
2
|
+
module BackgrounDRb
|
3
|
+
# raised when connection to a particular server failed
|
4
|
+
class BdrbConnError < RuntimeError
|
5
|
+
attr_accessor :message
|
6
|
+
def initialize(message)
|
7
|
+
@message = message
|
8
|
+
end
|
9
|
+
end
|
10
|
+
# raised when connection to all of the available servers failed
|
11
|
+
class NoServerAvailable < RuntimeError
|
12
|
+
attr_accessor :message
|
13
|
+
def initialize(message)
|
14
|
+
@message = message
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# raised, when said task was submitted without a job key, whereas
|
19
|
+
# nature of the task requires a job key
|
20
|
+
class NoJobKey < RuntimeError; end
|
21
|
+
|
22
|
+
# raised if worker throws some error
|
23
|
+
class RemoteWorkerError < RuntimeError
|
24
|
+
attr_accessor :message
|
25
|
+
def initialize message
|
26
|
+
@message = message
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
module BackgrounDRb
|
2
|
+
class Connection
|
3
|
+
attr_accessor :server_ip,:server_port,:cluster_conn,:connection_status
|
4
|
+
|
5
|
+
def initialize ip,port,cluster_conn
|
6
|
+
@mutex = Mutex.new
|
7
|
+
@server_ip = ip
|
8
|
+
@server_port = port
|
9
|
+
@cluster_conn = cluster_conn
|
10
|
+
@connection_status = true
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def establish_connection
|
15
|
+
begin
|
16
|
+
timeout(3) do
|
17
|
+
@connection = TCPSocket.open(server_ip, server_port)
|
18
|
+
@connection.setsockopt(Socket::IPPROTO_TCP,Socket::TCP_NODELAY,1)
|
19
|
+
end
|
20
|
+
@connection_status = true
|
21
|
+
rescue Timeout::Error
|
22
|
+
@connection_status = false
|
23
|
+
rescue Exception => e
|
24
|
+
@connection_status = false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def write_data data
|
29
|
+
begin
|
30
|
+
flush_in_loop(data)
|
31
|
+
rescue Errno::EAGAIN
|
32
|
+
return
|
33
|
+
rescue Errno::EPIPE
|
34
|
+
establish_connection
|
35
|
+
if @connection_status
|
36
|
+
flush_in_loop(data)
|
37
|
+
else
|
38
|
+
@connection_status = false
|
39
|
+
raise BackgrounDRb::BdrbConnError.new("Error while writing #{server_info}")
|
40
|
+
end
|
41
|
+
rescue
|
42
|
+
establish_connection
|
43
|
+
if @connection_status
|
44
|
+
flush_in_loop(data)
|
45
|
+
else
|
46
|
+
@connection_status = false
|
47
|
+
raise BackgrounDRb::BdrbConnError.new("Error while writing #{server_info}")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def server_info
|
53
|
+
"#{server_ip}:#{server_port}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def flush_in_loop(data)
|
57
|
+
t_length = data.length
|
58
|
+
loop do
|
59
|
+
break if t_length <= 0
|
60
|
+
written_length = @connection.write(data)
|
61
|
+
raise "Error writing to socket" if written_length <= 0
|
62
|
+
result = @connection.flush
|
63
|
+
data = data[written_length..-1]
|
64
|
+
t_length = data.length
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def dump_object data
|
69
|
+
establish_connection
|
70
|
+
raise BackgrounDRb::BdrbConnError.new("Error while connecting to the backgroundrb server #{server_info}") unless @connection_status
|
71
|
+
|
72
|
+
object_dump = Marshal.dump(data)
|
73
|
+
dump_length = object_dump.length.to_s
|
74
|
+
length_str = dump_length.rjust(9,'0')
|
75
|
+
final_data = length_str + object_dump
|
76
|
+
@mutex.synchronize { write_data(final_data) }
|
77
|
+
end
|
78
|
+
|
79
|
+
def close_connection
|
80
|
+
@connection.close
|
81
|
+
@connection = nil
|
82
|
+
end
|
83
|
+
|
84
|
+
def ask_work p_data
|
85
|
+
p_data[:type] = :async_invoke
|
86
|
+
dump_object(p_data)
|
87
|
+
bdrb_response = nil
|
88
|
+
@mutex.synchronize { bdrb_response = read_from_bdrb() }
|
89
|
+
close_connection
|
90
|
+
bdrb_response
|
91
|
+
end
|
92
|
+
|
93
|
+
def new_worker p_data
|
94
|
+
p_data[:type] = :start_worker
|
95
|
+
dump_object(p_data)
|
96
|
+
close_connection
|
97
|
+
# RailsWorkerProxy.worker(p_data[:worker],p_data[:worker_key],self)
|
98
|
+
end
|
99
|
+
|
100
|
+
def worker_info(p_data)
|
101
|
+
p_data[:type] = :worker_info
|
102
|
+
dump_object(p_data)
|
103
|
+
bdrb_response = nil
|
104
|
+
@mutex.synchronize { bdrb_response = read_from_bdrb() }
|
105
|
+
close_connection
|
106
|
+
bdrb_response
|
107
|
+
end
|
108
|
+
|
109
|
+
def all_worker_info
|
110
|
+
p_data = { }
|
111
|
+
p_data[:type] = :all_worker_info
|
112
|
+
dump_object(p_data)
|
113
|
+
bdrb_response = nil
|
114
|
+
@mutex.synchronize { bdrb_response = read_from_bdrb() }
|
115
|
+
close_connection
|
116
|
+
bdrb_response
|
117
|
+
end
|
118
|
+
|
119
|
+
def delete_worker p_data
|
120
|
+
p_data[:type] = :delete_worker
|
121
|
+
dump_object(p_data)
|
122
|
+
close_connection
|
123
|
+
end
|
124
|
+
|
125
|
+
def read_object
|
126
|
+
begin
|
127
|
+
message_length_str = @connection.read(9)
|
128
|
+
message_length = message_length_str.to_i
|
129
|
+
message_data = @connection.read(message_length)
|
130
|
+
return message_data
|
131
|
+
rescue
|
132
|
+
raise BackgrounDRb::BdrbConnError.new("Not able to connect #{server_info}")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def gen_key options
|
137
|
+
if BDRB_CONFIG[:backgroundrb][:result_storage] == 'memcache'
|
138
|
+
key = [options[:worker],options[:worker_key],options[:job_key]].compact.join('_')
|
139
|
+
key
|
140
|
+
else
|
141
|
+
options[:job_key]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def ask_result(p_data)
|
146
|
+
if BDRB_CONFIG[:backgroundrb][:result_storage] == 'memcache'
|
147
|
+
return_result_from_memcache(p_data)
|
148
|
+
else
|
149
|
+
p_data[:type] = :get_result
|
150
|
+
dump_object(p_data)
|
151
|
+
bdrb_response = nil
|
152
|
+
@mutex.synchronize { bdrb_response = read_from_bdrb() }
|
153
|
+
close_connection
|
154
|
+
bdrb_response ? bdrb_response[:data] : nil
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def read_from_bdrb(timeout = 3)
|
159
|
+
begin
|
160
|
+
ret_val = select([@connection],nil,nil,timeout)
|
161
|
+
return nil unless ret_val
|
162
|
+
raw_response = read_object()
|
163
|
+
master_response = Marshal.load(raw_response)
|
164
|
+
return master_response
|
165
|
+
rescue
|
166
|
+
return nil
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def send_request(p_data)
|
171
|
+
p_data[:type] = :sync_invoke
|
172
|
+
dump_object(p_data)
|
173
|
+
bdrb_response = nil
|
174
|
+
@mutex.synchronize { bdrb_response = read_from_bdrb(nil) }
|
175
|
+
close_connection
|
176
|
+
bdrb_response
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|