backgroundrb-rails3 1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. data/.autotest +17 -0
  2. data/ChangeLog +50 -0
  3. data/Gemfile +11 -0
  4. data/LICENSE +4 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README +22 -0
  7. data/Rakefile +128 -0
  8. data/TODO.org +5 -0
  9. data/app/controller/backgroundrb_status_controller.rb +6 -0
  10. data/backgroundrb-rails3.gemspec +219 -0
  11. data/config/backgroundrb.yml +11 -0
  12. data/doc/Rakefile +5 -0
  13. data/doc/config.yaml +2 -0
  14. data/doc/content/advanced/advanced.txt +76 -0
  15. data/doc/content/advanced/advanced.yaml +4 -0
  16. data/doc/content/bugs/bugs.txt +20 -0
  17. data/doc/content/bugs/bugs.yaml +5 -0
  18. data/doc/content/community/community.txt +36 -0
  19. data/doc/content/community/community.yaml +5 -0
  20. data/doc/content/content.txt +168 -0
  21. data/doc/content/content.yaml +5 -0
  22. data/doc/content/faq/faq.txt +41 -0
  23. data/doc/content/faq/faq.yaml +5 -0
  24. data/doc/content/rails/rails.txt +182 -0
  25. data/doc/content/rails/rails.yaml +5 -0
  26. data/doc/content/scheduling/scheduling.txt +166 -0
  27. data/doc/content/scheduling/scheduling.yaml +5 -0
  28. data/doc/content/workers/workers.txt +178 -0
  29. data/doc/content/workers/workers.yaml +5 -0
  30. data/doc/layouts/default/default.erb +56 -0
  31. data/doc/layouts/default/default.yaml +4 -0
  32. data/doc/lib/default.rb +7 -0
  33. data/doc/output/Assets/BG-Ad-Top.png +0 -0
  34. data/doc/output/Assets/BG-Body.png +0 -0
  35. data/doc/output/Assets/BG-Feed.png +0 -0
  36. data/doc/output/Assets/BG-Menu-Hover.png +0 -0
  37. data/doc/output/Assets/BG-Menu.png +0 -0
  38. data/doc/output/Assets/BG-Sidebar-Bottom.png +0 -0
  39. data/doc/output/Assets/Button-Feed.png +0 -0
  40. data/doc/output/images/bg-ad-top.png +0 -0
  41. data/doc/output/images/bg-body.png +0 -0
  42. data/doc/output/images/bg-feed.gif +0 -0
  43. data/doc/output/images/bg-footer.jpg +0 -0
  44. data/doc/output/images/bg-header.jpg +0 -0
  45. data/doc/output/images/bg-menu-hover.png +0 -0
  46. data/doc/output/images/bg-menu.png +0 -0
  47. data/doc/output/images/bg-sidebar-bottom.gif +0 -0
  48. data/doc/output/images/button-feed.png +0 -0
  49. data/doc/output/images/icon-comment.png +0 -0
  50. data/doc/output/images/more_icon.gif +0 -0
  51. data/doc/output/style.css +299 -0
  52. data/doc/page_defaults.yaml +13 -0
  53. data/doc/tasks/default.rake +3 -0
  54. data/doc/templates/default/default.txt +1 -0
  55. data/doc/templates/default/default.yaml +4 -0
  56. data/examples/backgroundrb.yml +25 -0
  57. data/examples/foo_controller.rb +48 -0
  58. data/examples/god_worker.rb +7 -0
  59. data/examples/worker_tests/god_worker_test.rb +8 -0
  60. data/examples/workers/error_worker.rb +17 -0
  61. data/examples/workers/foo_worker.rb +38 -0
  62. data/examples/workers/god_worker.rb +7 -0
  63. data/examples/workers/model_worker.rb +13 -0
  64. data/examples/workers/renewal_worker.rb +11 -0
  65. data/examples/workers/rss_worker.rb +26 -0
  66. data/examples/workers/server_worker.rb +31 -0
  67. data/examples/workers/world_worker.rb +12 -0
  68. data/examples/workers/xmpp_worker.rb +7 -0
  69. data/init.rb +7 -0
  70. data/install.rb +1 -0
  71. data/know_issues.org +5 -0
  72. data/lib/backgroundrb.rb +1 -0
  73. data/lib/backgroundrb/bdrb_client_helper.rb +8 -0
  74. data/lib/backgroundrb/bdrb_cluster_connection.rb +156 -0
  75. data/lib/backgroundrb/bdrb_config.rb +43 -0
  76. data/lib/backgroundrb/bdrb_conn_error.rb +29 -0
  77. data/lib/backgroundrb/bdrb_connection.rb +179 -0
  78. data/lib/backgroundrb/bdrb_job_queue.rb +79 -0
  79. data/lib/backgroundrb/bdrb_result.rb +19 -0
  80. data/lib/backgroundrb/bdrb_start_stop.rb +146 -0
  81. data/lib/backgroundrb/rails_worker_proxy.rb +181 -0
  82. data/lib/backgroundrb/railtie.rb +48 -0
  83. data/lib/generators/backgroundrb/bdrb_migration/USAGE +12 -0
  84. data/lib/generators/backgroundrb/bdrb_migration/bdrb_migration_generator.rb +15 -0
  85. data/lib/generators/backgroundrb/bdrb_migration/templates/migration.rb +27 -0
  86. data/lib/generators/backgroundrb/worker/USAGE +16 -0
  87. data/lib/generators/backgroundrb/worker/templates/unit_test.rb +12 -0
  88. data/lib/generators/backgroundrb/worker/templates/worker.rb +7 -0
  89. data/lib/generators/backgroundrb/worker/worker_generator.rb +14 -0
  90. data/lib/tasks/backgroundrb_tasks.rake +103 -0
  91. data/release_notes.org +48 -0
  92. data/release_points.org +46 -0
  93. data/script/backgroundrb +52 -0
  94. data/script/bdrb_test_helper.rb +99 -0
  95. data/script/load_worker_env.rb +31 -0
  96. data/script/monitrc +25 -0
  97. data/server/backgroundrb_server.rb +12 -0
  98. data/server/lib/bdrb_result_storage.rb +62 -0
  99. data/server/lib/bdrb_server_helper.rb +24 -0
  100. data/server/lib/bdrb_thread_pool.rb +127 -0
  101. data/server/lib/cron_trigger.rb +197 -0
  102. data/server/lib/invalid_dump_error.rb +4 -0
  103. data/server/lib/log_worker.rb +25 -0
  104. data/server/lib/master_proxy.rb +140 -0
  105. data/server/lib/master_worker.rb +187 -0
  106. data/server/lib/meta_worker.rb +432 -0
  107. data/server/lib/trigger.rb +34 -0
  108. data/test/bdrb_client_test_helper.rb +5 -0
  109. data/test/bdrb_test_helper.rb +35 -0
  110. data/test/client/backgroundrb.yml +17 -0
  111. data/test/client/test_bdrb_client_helper.rb +13 -0
  112. data/test/client/test_bdrb_cluster_connection.rb +162 -0
  113. data/test/client/test_bdrb_config.rb +20 -0
  114. data/test/client/test_bdrb_connection.rb +29 -0
  115. data/test/client/test_bdrb_job_queue.rb +63 -0
  116. data/test/client/test_worker_proxy.rb +130 -0
  117. data/test/server/test_cron_trigger.rb +281 -0
  118. data/test/server/test_master_proxy.rb +54 -0
  119. data/test/server/test_master_worker.rb +157 -0
  120. data/test/server/test_meta_worker.rb +281 -0
  121. data/test/server/test_result_storage.rb +14 -0
  122. data/test/socket_mocker.rb +34 -0
  123. data/test/workers/bar_worker.rb +10 -0
  124. data/test/workers/foo_worker.rb +10 -0
  125. data/uninstall.rb +1 -0
  126. 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,7 @@
1
+ class GodWorker < BackgrounDRb::MetaWorker
2
+ set_worker_name :god_worker
3
+ def create(args = nil)
4
+ logger.info "hello world"
5
+ end
6
+ end
7
+
@@ -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,11 @@
1
+ class RenewalWorker < BackgrounDRb::MetaWorker
2
+ set_worker_name :renewal_worker
3
+ def create(args = nil)
4
+
5
+ end
6
+ def load_policies(data = nil)
7
+ logger.info "Loading policies done on #{data}"
8
+ return "done"
9
+ end
10
+ end
11
+
@@ -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
+
@@ -0,0 +1,12 @@
1
+ class WorldWorker < BackgrounDRb::MetaWorker
2
+ set_worker_name :world_worker
3
+ def create(args = nil)
4
+ #logger.info "starting world worker"
5
+ end
6
+
7
+ def hello_world
8
+ a = lambda { "Hello world" }
9
+ return a
10
+ end
11
+ end
12
+
@@ -0,0 +1,7 @@
1
+ class XmppWorker < BackgrounDRb::MetaWorker
2
+ set_worker_name :xmpp_worker
3
+ def create(args = nil)
4
+ # this method is called, when worker is loaded for the first time
5
+ end
6
+ end
7
+
data/init.rb ADDED
@@ -0,0 +1,7 @@
1
+ # Include hook code here
2
+ %w{ controller }.each do |code_dir|
3
+ $:.unshift File.join(File.dirname(__FILE__),"app",code_dir)
4
+ end
5
+
6
+ require 'backgroundrb'
7
+ #require "backgroundrb_status_controller"
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
data/know_issues.org ADDED
@@ -0,0 +1,5 @@
1
+ * Some issues that I am aware of *
2
+ - Creation of job queue may fail on other that mysql dbs
3
+ - Database doesn't get created when someone runs the migrations again
4
+ - Delete doesn't seem to be working test it.
5
+
@@ -0,0 +1 @@
1
+ require "backgroundrb/railtie"
@@ -0,0 +1,8 @@
1
+ module BackgrounDRb
2
+ module ClientHelper
3
+ def gen_worker_key(worker_name,worker_key = nil)
4
+ return worker_name.to_sym if worker_key.nil?
5
+ return "#{worker_name}_#{worker_key}".to_sym
6
+ end
7
+ end
8
+ end
@@ -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