josip-backgroundrb_merb 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +4 -0
- data/README +45 -0
- data/Rakefile +44 -0
- data/TODO +8 -0
- data/config/backgroundrb.yml +11 -0
- data/generators/worker/USAGE +16 -0
- data/generators/worker/templates/app/workers/%worker_file_name%_worker.rb +7 -0
- data/generators/worker/templates/spec/workers/%worker_file_name%_spec.rb +9 -0
- data/generators/worker/worker_generator.rb +36 -0
- data/lib/backgroundrb_merb.rb +19 -0
- data/lib/backgroundrb_merb/bdrb_config.rb +47 -0
- data/lib/backgroundrb_merb/bdrb_conn_error.rb +9 -0
- data/lib/backgroundrb_merb/merb_worker_proxy.rb +57 -0
- data/lib/backgroundrb_merb/merbtasks.rb +91 -0
- data/lib/backgroundrb_merb/worker_proxy.rb +174 -0
- data/server/backgroundrb_server.rb +7 -0
- data/server/lib/cron_trigger.rb +195 -0
- data/server/lib/invalid_dump_error.rb +4 -0
- data/server/lib/log_worker.rb +25 -0
- data/server/lib/master_worker.rb +301 -0
- data/server/lib/meta_worker.rb +360 -0
- data/server/lib/trigger.rb +34 -0
- metadata +110 -0
@@ -0,0 +1,195 @@
|
|
1
|
+
module BackgrounDRbMerb
|
2
|
+
class CronTrigger
|
3
|
+
WDAYS = { 0 => "Sunday",1 => "Monday",2 => "Tuesday",3 => "Wednesday", 4 => "Thursday", 5 => "Friday", 6 => "Saturday" }
|
4
|
+
LeapYearMonthDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
5
|
+
CommonYearMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
6
|
+
|
7
|
+
attr_reader :sec, :min, :hour, :day, :month, :wday, :year, :cron_expr
|
8
|
+
|
9
|
+
def initialize(expr)
|
10
|
+
self.cron_expr = expr
|
11
|
+
end
|
12
|
+
|
13
|
+
def cron_expr=(expr)
|
14
|
+
@cron_expr = expr
|
15
|
+
self.sec, self.min, self.hour, self.day, self.month, self.wday, self.year = @cron_expr.split(' ')
|
16
|
+
end
|
17
|
+
|
18
|
+
def fire_after_time(p_time)
|
19
|
+
@t_sec,@t_min,@t_hour,@t_day,@t_month,@t_year,@t_wday,@t_yday,@t_idst,@t_zone = p_time.to_a
|
20
|
+
@count = 0
|
21
|
+
loop do
|
22
|
+
@count += 1
|
23
|
+
|
24
|
+
if @year && !@year.include?(@t_year)
|
25
|
+
return nil if @t_year > @year.max
|
26
|
+
@t_year = @year.detect { |y| y > @t_year }
|
27
|
+
end
|
28
|
+
|
29
|
+
# if range of months doesn't include current month, find next month from the range
|
30
|
+
unless @month.include?(@t_month)
|
31
|
+
next_month = @month.detect { |m| m > @t_month } || @month.min
|
32
|
+
@t_day,@t_hour,@t_min,@t_sec = @day.min,@hour.min,@min.min,@sec.min
|
33
|
+
if next_month < @t_month
|
34
|
+
@t_month = next_month
|
35
|
+
@t_year += 1
|
36
|
+
retry
|
37
|
+
end
|
38
|
+
@t_month = next_month
|
39
|
+
end
|
40
|
+
|
41
|
+
if !day_restricted? && wday_restricted?
|
42
|
+
unless @wday.include?(@t_wday)
|
43
|
+
next_wday = @wday.detect { |w| w > @t_wday} || @wday.min
|
44
|
+
@t_hour,@t_min,@t_sec = @hour.min,@min.min,@sec.min
|
45
|
+
t_time = Chronic.parse("next #{WDAYS[next_wday]}",:now => current_time)
|
46
|
+
@t_day,@t_month,@t_year = t_time.to_a[3..5]
|
47
|
+
@t_wday = next_wday
|
48
|
+
retry
|
49
|
+
end
|
50
|
+
elsif !wday_restricted? && day_restricted?
|
51
|
+
day_range = (1.. month_days(@t_year,@t_month))
|
52
|
+
# day array, that includes days which are present in current month
|
53
|
+
day_array = @day.select { |d| day_range === d }
|
54
|
+
unless day_array.include?(@t_day)
|
55
|
+
next_day = day_array.detect { |d| d > @t_day } || day_array.min
|
56
|
+
@t_hour,@t_min,@t_sec = @hour.min,@min.min,@sec.min
|
57
|
+
if !next_day || next_day < @t_day
|
58
|
+
t_time = Chronic.parse("next month",:now => current_time)
|
59
|
+
@t_day = next_day.nil? ? @day.min : next_day
|
60
|
+
@t_month,@t_year = t_time.month,t_time.year
|
61
|
+
retry
|
62
|
+
end
|
63
|
+
@t_day = next_day
|
64
|
+
end
|
65
|
+
else
|
66
|
+
# if both day and wday are restricted cron should give preference to one thats closer to current time
|
67
|
+
day_range = (1 .. month_days(@t_year,@t_month))
|
68
|
+
day_array = @day.select { |d| day_range === d }
|
69
|
+
if !day_array.include?(@t_day) && !@wday.include?(@t_wday)
|
70
|
+
next_day = day_array.detect { |d| d > @t_day } || day_array.min
|
71
|
+
next_wday = @wday.detect { |w| w > @t_wday } || @wday.min
|
72
|
+
@t_hour,@t_min,@t_sec = @hour.min,@min.min,@sec.min
|
73
|
+
|
74
|
+
# if next_day is nil or less than @t_day it means that it should run in next month
|
75
|
+
if !next_day || next_day < @t_day
|
76
|
+
next_time_mday = Chronic.parse("next month",:now => current_time)
|
77
|
+
else
|
78
|
+
@t_day = next_day
|
79
|
+
next_time_mday = current_time
|
80
|
+
end
|
81
|
+
next_time_wday = Chronic.parse("next #{WDAYS[next_wday]}",:now => current_time)
|
82
|
+
if next_time_mday < next_time_wday
|
83
|
+
@t_day,@t_month,@t_year = next_time_mday.to_a[3..5]
|
84
|
+
else
|
85
|
+
@t_day,@t_month,@t_year = next_time_wday.to_a[3..5]
|
86
|
+
end
|
87
|
+
retry
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
unless @hour.include?(@t_hour)
|
92
|
+
next_hour = @hour.detect { |h| h > @t_hour } || @hour.min
|
93
|
+
@t_min,@t_sec = @min.min,@sec.min
|
94
|
+
if next_hour < @t_hour
|
95
|
+
@t_hour = next_hour
|
96
|
+
next_day = Chronic.parse("next day",:now => current_time)
|
97
|
+
@t_day,@t_month,@t_year,@t_wday = next_day.to_a[3..6]
|
98
|
+
retry
|
99
|
+
end
|
100
|
+
@t_hour = next_hour
|
101
|
+
end
|
102
|
+
|
103
|
+
unless @min.include?(@t_min)
|
104
|
+
next_min = @min.detect { |m| m > @t_min } || @min.min
|
105
|
+
@t_sec = @sec.min
|
106
|
+
if next_min < @t_min
|
107
|
+
@t_min = next_min
|
108
|
+
next_hour = Chronic.parse("next hour",:now => current_time)
|
109
|
+
@t_hour,@t_day,@t_month,@t_year,@t_wday = next_hour.to_a[2..6]
|
110
|
+
retry
|
111
|
+
end
|
112
|
+
@t_min = next_min
|
113
|
+
end
|
114
|
+
|
115
|
+
unless @sec.include?(@t_sec)
|
116
|
+
next_sec = @sec.detect { |s| s > @t_sec } || @sec.min
|
117
|
+
if next_sec < @t_sec
|
118
|
+
@t_sec = next_sec
|
119
|
+
next_min = Chronic.parse("next minute",:now => current_time)
|
120
|
+
@t_min,@t_hour,@t_day,@t_month,@t_year,@t_wday = next_min.to_a[1..6]
|
121
|
+
retry
|
122
|
+
end
|
123
|
+
@t_sec = next_sec
|
124
|
+
end
|
125
|
+
break
|
126
|
+
end # end of loop do
|
127
|
+
current_time
|
128
|
+
end
|
129
|
+
|
130
|
+
def current_time
|
131
|
+
Time.local(@t_sec,@t_min,@t_hour,@t_day,@t_month,@t_year,@t_wday,nil,@t_idst,@t_zone)
|
132
|
+
end
|
133
|
+
|
134
|
+
def day_restricted?
|
135
|
+
return !@day.eql?(1..31)
|
136
|
+
end
|
137
|
+
|
138
|
+
def wday_restricted?
|
139
|
+
return !@wday.eql?(0..6)
|
140
|
+
end
|
141
|
+
|
142
|
+
# TODO: mimic attr_reader to define all of these
|
143
|
+
def sec=(sec); @sec = parse_part(sec, 0 .. 59); end
|
144
|
+
|
145
|
+
def min=(min); @min = parse_part(min, 0 .. 59); end
|
146
|
+
|
147
|
+
def hour=(hour); @hour = parse_part(hour, 0 .. 23); end
|
148
|
+
|
149
|
+
def day=(day)
|
150
|
+
@day = parse_part(day, 1 .. 31)
|
151
|
+
end
|
152
|
+
|
153
|
+
def month=(month)
|
154
|
+
@month = parse_part(month, 1 .. 12)
|
155
|
+
end
|
156
|
+
|
157
|
+
def year=(year)
|
158
|
+
@year = parse_part(year)
|
159
|
+
end
|
160
|
+
|
161
|
+
def wday=(wday)
|
162
|
+
@wday = parse_part(wday, 0 .. 6)
|
163
|
+
end
|
164
|
+
private
|
165
|
+
def month_days(y, m)
|
166
|
+
if ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)
|
167
|
+
LeapYearMonthDays[m-1]
|
168
|
+
else
|
169
|
+
CommonYearMonthDays[m-1]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# 0-5,8,10; 0-5; *; */5
|
174
|
+
def parse_part(part, range=nil)
|
175
|
+
return range if part.nil? or part == '*' or part =~ /^[*0]\/1$/
|
176
|
+
|
177
|
+
r = Array.new
|
178
|
+
part.split(',').each do |p|
|
179
|
+
if p =~ /-/ # 0-5
|
180
|
+
r << Range.new(*(p.scan(/\d+/).map { |x| x.to_i })).map { |x| x.to_i }
|
181
|
+
elsif p =~ /(\*|\d+)\/(\d+)/ && range # */5, 2/10
|
182
|
+
min = $1 == '*' ? 0 : $1.to_i
|
183
|
+
inc = $2.to_i
|
184
|
+
(min .. range.end).each_with_index do |x, i|
|
185
|
+
r << (range.begin == 1 ? x + 1 : x) if i % inc == 0
|
186
|
+
end
|
187
|
+
else
|
188
|
+
r << p.to_i
|
189
|
+
end
|
190
|
+
end
|
191
|
+
r.flatten
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class LogWorker < Packet::Worker
|
2
|
+
set_worker_name :log_worker
|
3
|
+
attr_accessor :log_file
|
4
|
+
|
5
|
+
def worker_init
|
6
|
+
file = Merb.root / "log" / "backgroundrb_#{CONFIG_FILE[:backgroundrb][:port]}.log"
|
7
|
+
@log_file = Merb::Logger.new(file, :debug, "", true)
|
8
|
+
end
|
9
|
+
|
10
|
+
def receive_data(p_data)
|
11
|
+
case p_data[:type]
|
12
|
+
when :request: process_request(p_data)
|
13
|
+
when :response: process_response(p_data)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def process_request(p_data)
|
18
|
+
log_data = p_data[:data]
|
19
|
+
@log_file << "[I] " + log_data
|
20
|
+
end
|
21
|
+
|
22
|
+
def process_response
|
23
|
+
puts "Not implemented and needed"
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,301 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
module BackgrounDRbMerb
|
3
|
+
# Class wraps a logger object for debugging internal errors within server
|
4
|
+
class DebugMaster
|
5
|
+
attr_accessor :log_mode,:logger,:log_flag
|
6
|
+
def initialize(log_mode,log_flag = true)
|
7
|
+
@log_mode = log_mode
|
8
|
+
@log_flag = log_flag
|
9
|
+
if @log_mode == :foreground
|
10
|
+
@logger = ::Logger.new(STDOUT)
|
11
|
+
else
|
12
|
+
@logger = ::Logger.new("#{Merb.root}/log/backgroundrb_#{CONFIG_FILE[:backgroundrb][:port]}_debug.log")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def info(data)
|
17
|
+
return unless @log_flag
|
18
|
+
@logger.info(data)
|
19
|
+
end
|
20
|
+
|
21
|
+
def debug(data)
|
22
|
+
return unless @log_flag
|
23
|
+
@logger.debug(data)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class MasterWorker
|
28
|
+
attr_accessor :debug_logger
|
29
|
+
def receive_data p_data
|
30
|
+
debug_logger.info(p_data)
|
31
|
+
@tokenizer.extract(p_data) do |b_data|
|
32
|
+
t_data = Marshal.load(b_data)
|
33
|
+
debug_logger.info(t_data)
|
34
|
+
case t_data[:type]
|
35
|
+
when :do_work: process_work(t_data)
|
36
|
+
when :get_status: process_status(t_data)
|
37
|
+
when :get_result: process_request(t_data)
|
38
|
+
when :start_worker: start_worker_request(t_data)
|
39
|
+
when :delete_worker: delete_drb_worker(t_data)
|
40
|
+
when :all_worker_status: query_all_worker_status(t_data)
|
41
|
+
when :worker_info: pass_worker_info(t_data)
|
42
|
+
when :all_worker_info: all_worker_info(t_data)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
def pass_worker_info(t_data)
|
49
|
+
worker_name_key = gen_worker_key(t_data[:worker],t_data[:job_key])
|
50
|
+
worker_instance = reactor.live_workers[worker_name_key]
|
51
|
+
info_response = { :worker => t_data[:worker],:job_key => t_data[:job_key]}
|
52
|
+
worker_instance ? (info_response[:status] = :running) : (info_response[:status] = :stopped)
|
53
|
+
send_object(info_response)
|
54
|
+
end
|
55
|
+
|
56
|
+
def all_worker_info(t_data)
|
57
|
+
info_response = []
|
58
|
+
reactor.live_workers.each do |key,value|
|
59
|
+
job_key = (value.worker_key.to_s).gsub(/#{value.worker_name}_?/,"")
|
60
|
+
info_response << { :worker => value.worker_name,:job_key => job_key,:status => :running }
|
61
|
+
end
|
62
|
+
send_object(info_response)
|
63
|
+
end
|
64
|
+
|
65
|
+
def query_all_worker_status(p_data)
|
66
|
+
dumpable_status = { }
|
67
|
+
reactor.live_workers.each { |key,value| dumpable_status[key] = reactor.result_hash[key] }
|
68
|
+
send_object(dumpable_status)
|
69
|
+
end
|
70
|
+
|
71
|
+
# FIXME: although worker key is removed nonetheless from live_workers hash
|
72
|
+
# it could be a good idea to remove it here itself.
|
73
|
+
def delete_drb_worker(t_data)
|
74
|
+
worker_name = t_data[:worker]
|
75
|
+
job_key = t_data[:job_key]
|
76
|
+
worker_name_key = gen_worker_key(worker_name,job_key)
|
77
|
+
begin
|
78
|
+
# ask_worker(worker_name,:job_key => t_data[:job_key],:type => :request, :data => { :worker_method => :exit})
|
79
|
+
worker_instance = reactor.live_workers[worker_name_key]
|
80
|
+
# pgid = Process.getpgid(worker_instance.pid)
|
81
|
+
Process.kill('TERM',worker_instance.pid)
|
82
|
+
# Process.kill('-TERM',pgid)
|
83
|
+
|
84
|
+
# Process.kill('KILL',worker_instance.pid)
|
85
|
+
rescue Packet::DisconnectError => sock_error
|
86
|
+
# reactor.live_workers.delete(worker_name_key)
|
87
|
+
reactor.remove_worker(sock_error)
|
88
|
+
rescue
|
89
|
+
debug_logger.info($!.to_s)
|
90
|
+
debug_logger.info($!.backtrace.join("\n"))
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def start_worker_request(p_data)
|
95
|
+
start_worker(p_data)
|
96
|
+
end
|
97
|
+
|
98
|
+
def process_work(t_data)
|
99
|
+
worker_name = t_data[:worker]
|
100
|
+
worker_name_key = gen_worker_key(worker_name,t_data[:job_key])
|
101
|
+
t_data.delete(:worker)
|
102
|
+
t_data.delete(:type)
|
103
|
+
begin
|
104
|
+
ask_worker(worker_name_key,:data => t_data, :type => :request, :result => false)
|
105
|
+
rescue Packet::DisconnectError => sock_error
|
106
|
+
reactor.live_workers.delete(worker_name_key)
|
107
|
+
rescue
|
108
|
+
debug_logger.info($!.to_s)
|
109
|
+
debug_logger.info($!.backtrace.join("\n"))
|
110
|
+
return
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
def process_status(t_data)
|
116
|
+
worker_name = t_data[:worker]
|
117
|
+
job_key = t_data[:job_key]
|
118
|
+
worker_name_key = gen_worker_key(worker_name,job_key)
|
119
|
+
status_data = reactor.result_hash[worker_name_key.to_sym]
|
120
|
+
send_object(status_data)
|
121
|
+
end
|
122
|
+
|
123
|
+
def process_request(t_data)
|
124
|
+
worker_name = t_data[:worker]
|
125
|
+
worker_name_key = gen_worker_key(worker_name,t_data[:job_key])
|
126
|
+
t_data.delete(:worker)
|
127
|
+
t_data.delete(:type)
|
128
|
+
begin
|
129
|
+
ask_worker(worker_name_key,:data => t_data, :type => :request,:result => true)
|
130
|
+
rescue Packet::DisconnectError => sock_error
|
131
|
+
reactor.live_workers.delete(worker_name_key)
|
132
|
+
rescue
|
133
|
+
debug_logger.info($!.to_s)
|
134
|
+
debug_logger.info($!.backtrace.join("\n"))
|
135
|
+
return
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# this method can receive one shot status reports or proper results
|
140
|
+
def worker_receive p_data
|
141
|
+
send_object(p_data)
|
142
|
+
end
|
143
|
+
|
144
|
+
def unbind
|
145
|
+
debug_logger.info("Client disconected")
|
146
|
+
end
|
147
|
+
def post_init
|
148
|
+
@tokenizer = BinParser.new
|
149
|
+
end
|
150
|
+
def connection_completed; end
|
151
|
+
end
|
152
|
+
|
153
|
+
class MasterProxy
|
154
|
+
attr_accessor :config_file,:reloadable_workers,:worker_triggers,:reactor
|
155
|
+
def initialize
|
156
|
+
raise "Running old Ruby version, upgrade to Ruby >= 1.8.5" unless check_for_ruby_version
|
157
|
+
@config_file = BackgrounDRbMerb::Config.read_config("#{Merb.root}/config/backgroundrb.yml")
|
158
|
+
|
159
|
+
log_flag = CONFIG_FILE[:backgroundrb][:debug_log].nil? ? true : CONFIG_FILE[:backgroundrb][:debug_log]
|
160
|
+
debug_logger = DebugMaster.new(CONFIG_FILE[:backgroundrb][:log],log_flag)
|
161
|
+
|
162
|
+
load_merb_env
|
163
|
+
|
164
|
+
find_reloadable_worker
|
165
|
+
|
166
|
+
Packet::Reactor.run do |t_reactor|
|
167
|
+
@reactor = t_reactor
|
168
|
+
enable_memcache_result_hash(t_reactor) if CONFIG_FILE[:backgroundrb][:result_storage] && CONFIG_FILE[:backgroundrb][:result_storage][:memcache]
|
169
|
+
t_reactor.start_worker(:worker => :log_worker) if log_flag
|
170
|
+
t_reactor.start_server(CONFIG_FILE[:backgroundrb][:ip],CONFIG_FILE[:backgroundrb][:port],MasterWorker) { |conn| conn.debug_logger = debug_logger }
|
171
|
+
t_reactor.next_turn { reload_workers }
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def gen_worker_key(worker_name,job_key = nil)
|
176
|
+
return worker_name if job_key.nil?
|
177
|
+
return "#{worker_name}_#{job_key}".to_sym
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
# method should find reloadable workers and load their schedule from config file
|
182
|
+
def find_reloadable_worker
|
183
|
+
t_workers = Dir["#{WORKER_ROOT}/**/*.rb"]
|
184
|
+
@reloadable_workers = t_workers.map do |x|
|
185
|
+
worker_name = File.basename(x,".rb")
|
186
|
+
require worker_name
|
187
|
+
worker_klass = Object.const_get(worker_name.camel_case)
|
188
|
+
worker_klass.reload_flag ? worker_klass : nil
|
189
|
+
end.compact
|
190
|
+
@worker_triggers = { }
|
191
|
+
@reloadable_workers.each do |t_worker|
|
192
|
+
schedule = load_reloadable_schedule(t_worker)
|
193
|
+
if schedule && !schedule.empty?
|
194
|
+
@worker_triggers[t_worker.worker_name.to_sym] = schedule
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def load_reloadable_schedule(t_worker)
|
200
|
+
worker_method_triggers = { }
|
201
|
+
worker_schedule = CONFIG_FILE[:schedules][t_worker.worker_name.to_sym]
|
202
|
+
|
203
|
+
worker_schedule && worker_schedule.each do |key,value|
|
204
|
+
case value[:trigger_args]
|
205
|
+
when String
|
206
|
+
cron_args = value[:trigger_args] || "0 0 0 0 0"
|
207
|
+
trigger = BackgrounDRbMerb::CronTrigger.new(cron_args)
|
208
|
+
when Hash
|
209
|
+
trigger = BackgrounDRbMerb::Trigger.new(value[:trigger_args])
|
210
|
+
end
|
211
|
+
worker_method_triggers[key] = { :trigger => trigger,:data => value[:data],:runtime => trigger.fire_after_time(Time.now).to_i }
|
212
|
+
end
|
213
|
+
worker_method_triggers
|
214
|
+
end
|
215
|
+
|
216
|
+
# method will reload workers that should be loaded on each schedule
|
217
|
+
def reload_workers
|
218
|
+
return if worker_triggers.empty?
|
219
|
+
worker_triggers.each do |key,value|
|
220
|
+
value.delete_if { |key,value| value[:trigger].respond_to?(:end_time) && value[:trigger].end_time <= Time.now }
|
221
|
+
end
|
222
|
+
|
223
|
+
worker_triggers.each do |worker_name,trigger|
|
224
|
+
trigger.each do |key,value|
|
225
|
+
time_now = Time.now.to_i
|
226
|
+
if value[:runtime] < time_now
|
227
|
+
load_and_invoke(worker_name,key,value)
|
228
|
+
t_time = value[:trigger].fire_after_time(Time.now)
|
229
|
+
value[:runtime] = t_time.to_i
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
# method will load the worker and invoke worker method
|
236
|
+
def load_and_invoke(worker_name,p_method,data)
|
237
|
+
begin
|
238
|
+
require worker_name.to_s
|
239
|
+
job_key = Packet::Guid.hexdigest
|
240
|
+
@reactor.start_worker(:worker => worker_name,:job_key => job_key)
|
241
|
+
worker_name_key = gen_worker_key(worker_name,job_key)
|
242
|
+
data_request = {:data => { :worker_method => p_method,:data => data[:data]},
|
243
|
+
:type => :request, :result => false
|
244
|
+
}
|
245
|
+
|
246
|
+
exit_request = {:data => { :worker_method => :exit},
|
247
|
+
:type => :request, :result => false
|
248
|
+
}
|
249
|
+
|
250
|
+
@reactor.live_workers[worker_name_key].send_request(data_request)
|
251
|
+
@reactor.live_workers[worker_name_key].send_request(exit_request)
|
252
|
+
rescue LoadError
|
253
|
+
puts "no such worker #{worker_name}"
|
254
|
+
rescue MissingSourceFile
|
255
|
+
puts "no such worker #{worker_name}"
|
256
|
+
return
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def load_merb_env
|
261
|
+
run_env = CONFIG_FILE[:backgroundrb][:environment] || 'development'
|
262
|
+
lazy_load = CONFIG_FILE[:backgroundrb][:lazy_load].nil? ? true : CONFIG_FILE[:backgroundrb][:lazy_load].nil?
|
263
|
+
require_merb_files unless lazy_load
|
264
|
+
ActiveRecord::Base.allow_concurrency = true if defined?(ActiveRecord)
|
265
|
+
end
|
266
|
+
|
267
|
+
def require_merb_files
|
268
|
+
debug_logger = DebugMaster.new(CONFIG_FILE[:backgroundrb][:log],true)
|
269
|
+
|
270
|
+
files = Dir["#{Merb.root}/app/models/**/*.rb"]
|
271
|
+
files.each { |x|
|
272
|
+
puts "***(M) #{x}"
|
273
|
+
begin
|
274
|
+
require x unless defined? x.camel_case
|
275
|
+
rescue LoadError
|
276
|
+
next
|
277
|
+
rescue MissingSourceFile
|
278
|
+
next
|
279
|
+
end
|
280
|
+
}
|
281
|
+
end
|
282
|
+
|
283
|
+
def enable_memcache_result_hash(t_reactor)
|
284
|
+
require 'memcache'
|
285
|
+
memcache_options = {
|
286
|
+
:c_threshold => 10_000,
|
287
|
+
:compression => true,
|
288
|
+
:debug => false,
|
289
|
+
:namespace => 'backgroundrb_result_hash',
|
290
|
+
:readonly => false,
|
291
|
+
:urlencode => false
|
292
|
+
}
|
293
|
+
cache = MemCache.new(memcache_options)
|
294
|
+
cache.servers = CONFIG_FILE[:backgroundrb][:result_storage][:memcache].split(',')
|
295
|
+
t_reactor.set_result_hash(cache)
|
296
|
+
end
|
297
|
+
|
298
|
+
def check_for_ruby_version; return RUBY_VERSION >= "1.8.5"; end
|
299
|
+
|
300
|
+
end # end of module BackgrounDRb
|
301
|
+
end
|