ambethia-bj 1.2.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.
Files changed (86) hide show
  1. data/HISTORY +80 -0
  2. data/LICENSE +1 -0
  3. data/README +318 -0
  4. data/Rakefile +20 -0
  5. data/TODO +53 -0
  6. data/VERSION +1 -0
  7. data/bin/bj +692 -0
  8. data/bj.gemspec +150 -0
  9. data/init.rb +1 -0
  10. data/install.rb +214 -0
  11. data/lib/bj.rb +85 -0
  12. data/lib/bj/api.rb +164 -0
  13. data/lib/bj/bj.rb +72 -0
  14. data/lib/bj/errors.rb +4 -0
  15. data/lib/bj/joblist.rb +112 -0
  16. data/lib/bj/logger.rb +50 -0
  17. data/lib/bj/runner.rb +330 -0
  18. data/lib/bj/stdext.rb +86 -0
  19. data/lib/bj/table.rb +426 -0
  20. data/lib/bj/util.rb +133 -0
  21. data/plugin/HISTORY +3 -0
  22. data/plugin/README +142 -0
  23. data/plugin/Rakefile +22 -0
  24. data/plugin/init.rb +33 -0
  25. data/plugin/install.rb +95 -0
  26. data/plugin/script/bj +55 -0
  27. data/plugin/tasks/bj_tasks.rake +4 -0
  28. data/plugin/test/bj_test.rb +8 -0
  29. data/plugin/uninstall.rb +1 -0
  30. data/spec/bj.rb +80 -0
  31. data/spec/helper.rb +85 -0
  32. data/spec/rails_root/README +256 -0
  33. data/spec/rails_root/Rakefile +10 -0
  34. data/spec/rails_root/app/controllers/application.rb +15 -0
  35. data/spec/rails_root/app/helpers/application_helper.rb +3 -0
  36. data/spec/rails_root/config/boot.rb +109 -0
  37. data/spec/rails_root/config/database.yml +23 -0
  38. data/spec/rails_root/config/environment.rb +67 -0
  39. data/spec/rails_root/config/environments/development.rb +17 -0
  40. data/spec/rails_root/config/environments/production.rb +22 -0
  41. data/spec/rails_root/config/environments/test.rb +22 -0
  42. data/spec/rails_root/config/initializers/inflections.rb +10 -0
  43. data/spec/rails_root/config/initializers/mime_types.rb +5 -0
  44. data/spec/rails_root/config/initializers/new_rails_defaults.rb +15 -0
  45. data/spec/rails_root/config/routes.rb +41 -0
  46. data/spec/rails_root/db/development.sqlite3 +0 -0
  47. data/spec/rails_root/db/migrate/20080909151517_bj_migration0.rb +8 -0
  48. data/spec/rails_root/db/schema.rb +62 -0
  49. data/spec/rails_root/doc/README_FOR_APP +2 -0
  50. data/spec/rails_root/log/development.log +141 -0
  51. data/spec/rails_root/log/production.log +0 -0
  52. data/spec/rails_root/log/server.log +0 -0
  53. data/spec/rails_root/log/test.log +0 -0
  54. data/spec/rails_root/public/404.html +30 -0
  55. data/spec/rails_root/public/422.html +30 -0
  56. data/spec/rails_root/public/500.html +30 -0
  57. data/spec/rails_root/public/dispatch.cgi +10 -0
  58. data/spec/rails_root/public/dispatch.fcgi +24 -0
  59. data/spec/rails_root/public/dispatch.rb +10 -0
  60. data/spec/rails_root/public/favicon.ico +0 -0
  61. data/spec/rails_root/public/images/rails.png +0 -0
  62. data/spec/rails_root/public/index.html +274 -0
  63. data/spec/rails_root/public/javascripts/application.js +2 -0
  64. data/spec/rails_root/public/javascripts/controls.js +963 -0
  65. data/spec/rails_root/public/javascripts/dragdrop.js +972 -0
  66. data/spec/rails_root/public/javascripts/effects.js +1120 -0
  67. data/spec/rails_root/public/javascripts/prototype.js +4225 -0
  68. data/spec/rails_root/public/robots.txt +5 -0
  69. data/spec/rails_root/script/about +3 -0
  70. data/spec/rails_root/script/bj +679 -0
  71. data/spec/rails_root/script/console +3 -0
  72. data/spec/rails_root/script/dbconsole +3 -0
  73. data/spec/rails_root/script/destroy +3 -0
  74. data/spec/rails_root/script/generate +3 -0
  75. data/spec/rails_root/script/performance/benchmarker +3 -0
  76. data/spec/rails_root/script/performance/profiler +3 -0
  77. data/spec/rails_root/script/performance/request +3 -0
  78. data/spec/rails_root/script/plugin +3 -0
  79. data/spec/rails_root/script/process/inspector +3 -0
  80. data/spec/rails_root/script/process/reaper +3 -0
  81. data/spec/rails_root/script/process/spawner +3 -0
  82. data/spec/rails_root/script/runner +3 -0
  83. data/spec/rails_root/script/server +3 -0
  84. data/spec/rails_root/test/test_helper.rb +38 -0
  85. data/todo.yml +23 -0
  86. metadata +184 -0
@@ -0,0 +1,164 @@
1
+ class Bj
2
+ #
3
+ # the api exposes nearly all the bj code you'll likely need, with the
4
+ # exception of accessing the job table for searching, which is done using
5
+ #
6
+ # eg.
7
+ #
8
+ # Bj.table.job.find :all
9
+ #
10
+ module API
11
+ #
12
+ # submit jobs for background processing. 'jobs' can be a string or array of
13
+ # strings. options are applied to each job in the 'jobs', and the list of
14
+ # submitted jobs is always returned. options (string or symbol) can be
15
+ #
16
+ # :rails_env => production|development|key_in_database_yml
17
+ # when given this keyword causes bj to submit jobs to the
18
+ # specified database. default is RAILS_ENV.
19
+ #
20
+ # :priority => any number, including negative ones. default is zero.
21
+ #
22
+ # :tag => a tag added to the job. simply makes searching easier.
23
+ #
24
+ # :env => a hash specifying any additional environment vars the background
25
+ # process should have.
26
+ #
27
+ # :stdin => any stdin the background process should have.
28
+ #
29
+ # eg:
30
+ #
31
+ # jobs = Bj.submit 'echo foobar', :tag => 'simple job'
32
+ #
33
+ # jobs = Bj.submit '/bin/cat', :stdin => 'in the hat', :priority => 42
34
+ #
35
+ # jobs = Bj.submit './script/runner ./scripts/a.rb', :rails_env => 'production'
36
+ #
37
+ # jobs = Bj.submit './script/runner /dev/stdin', :stdin => 'p RAILS_ENV', :tag => 'dynamic ruby code'
38
+ #
39
+ # jobs = Bj.submit array_of_commands, :priority => 451
40
+ #
41
+ # when jobs are run, they are run in RAILS_ROOT. various attributes are
42
+ # available *only* once the job has finished. you can check whether or not
43
+ # a job is finished by using the #finished method, which simple does a
44
+ # reload and checks to see if the exit_status is non-nil.
45
+ #
46
+ # eg:
47
+ #
48
+ # jobs = Bj.submit list_of_jobs, :tag => 'important'
49
+ # ...
50
+ #
51
+ # jobs.each do |job|
52
+ # if job.finished?
53
+ # p job.exit_status
54
+ # p job.stdout
55
+ # p job.stderr
56
+ # end
57
+ # end
58
+ #
59
+ #
60
+ def submit jobs, options = {}, &block
61
+ options.to_options!
62
+ Bj.transaction(options) do
63
+ table.job.submit jobs, options, &block
64
+ end
65
+ ensure
66
+ Bj.runner.tickle unless options[:no_tickle]
67
+ end
68
+ #
69
+ # this method changes the context under which bj is operating. a context is
70
+ # a RAILS_ENV. the method accepts a block and it used to alter the
71
+ # behaviour of the bj lib on a global scale such that all operations,
72
+ # spawning of background runnner processes, etc, occur in that context.
73
+ #
74
+ # eg:
75
+ #
76
+ # Bj.in :production do
77
+ # Bj.submit './script/runner ./scripts/facebook_notification.rb'
78
+ # end
79
+ #
80
+ # Bj.in :development do
81
+ # Bj.submit 'does_this_eat_memory.exe'
82
+ # end
83
+ #
84
+ def in rails_env = Bj.rails_env, &block
85
+ transaction(:rails_env => rails_env.to_s, &block)
86
+ end
87
+ #
88
+ # list simply returns a list of all jobs in the job table
89
+ #
90
+ def list options = {}, &block
91
+ options.to_options!
92
+ Bj.transaction(options) do
93
+ options.delete :rails_env
94
+ table.job.find(:all, options)
95
+ end
96
+ end
97
+ #
98
+ #
99
+ #
100
+ def run options = {}
101
+ runner.run options
102
+ end
103
+ #
104
+ # generate a migration and migrate a database (production/development/etc)
105
+ #
106
+ def setup options = {}
107
+ options.to_options!
108
+ chroot do
109
+ generate_migration options
110
+ migrate options
111
+ end
112
+ end
113
+ #
114
+ # generate_migration, suprisingly, generates the single migration needed for
115
+ # bj. you'll notice the the migration is very short as the migration
116
+ # classes themselves are inner classes of the respective bj table class.
117
+ # see lib/bj/table.rb for details.
118
+ #
119
+ def generate_migration options = {}
120
+ options.to_options!
121
+ options[:verbose] = true
122
+ chroot do
123
+ before = Dir.glob "./db/migrate/*"
124
+ n = Dir.glob("./db/migrate/*_bj_*").size
125
+ classname = "BjMigration#{ n }"
126
+ util.spawn "#{ Bj.ruby } ./script/generate migration #{ classname }", options rescue nil
127
+ after = Dir.glob "./db/migrate/*"
128
+ candidates = after - before
129
+ case candidates.size
130
+ when 0
131
+ false
132
+ when 1
133
+ generated = candidates.first
134
+ open(generated, "w"){|fd| fd.puts Bj.table.migration_code(classname)}
135
+ Bj.logger.info{ "generated <#{ generated }>" }
136
+ generated
137
+ else
138
+ raise "ambiguous migration <#{ candidates.inspect }>"
139
+ end
140
+ end
141
+ end
142
+ #
143
+ # migrate a database (production|development|etc)
144
+ #
145
+ def migrate options = {}
146
+ options.to_options!
147
+ options[:verbose] = true
148
+ chroot do
149
+ util.spawn "#{ Bj.rake } RAILS_ENV=#{ Bj.rails_env } db:migrate", options
150
+ end
151
+ end
152
+ #
153
+ # install plugin into this rails app
154
+ #
155
+ def plugin options = {}
156
+ options.to_options!
157
+ options[:verbose] = true
158
+ chroot do
159
+ util.spawn "#{ Bj.ruby } ./script/plugin install http://codeforpeople.rubyforge.org/svn/rails/plugins/bj --force", options
160
+ end
161
+ end
162
+ end
163
+ send :extend, API
164
+ end
@@ -0,0 +1,72 @@
1
+ class Bj
2
+ module ClassMethods
3
+ fattr("rails_root"){ Util.const_or_env("RAILS_ROOT"){ "." } }
4
+ fattr("rails_env"){ Util.const_or_env("RAILS_ENV"){ "development" } }
5
+ fattr("database_yml"){ File.join rails_root, "config", "database.yml" }
6
+ fattr("configurations"){ YAML::load(ERB.new(IO.read(database_yml)).result) }
7
+ fattr("tables"){ Table.list }
8
+ fattr("hostname"){ Socket.gethostname }
9
+ fattr("logger"){ Bj::Logger.off STDERR }
10
+ fattr("ruby"){ Util.which_ruby }
11
+ fattr("rake"){ Util.which_rake }
12
+ fattr("script"){ Util.find_script "bj" }
13
+ fattr("ttl"){ Integer(Bj::Table::Config["ttl"] || (twenty_four_hours = 24 * 60 * 60)) }
14
+ fattr("table"){ Table }
15
+ fattr("config"){ table.config }
16
+ fattr("util"){ Util }
17
+ fattr("runner"){ Runner }
18
+ fattr("joblist"){ Joblist }
19
+ fattr("default_path"){ %w'/bin /usr/bin /usr/local/bin /opt/local/bin'.join(File::PATH_SEPARATOR) }
20
+
21
+ def transaction options = {}, &block
22
+ options.to_options!
23
+
24
+ cur_rails_env = Bj.rails_env.to_s
25
+ new_rails_env = options[:rails_env].to_s
26
+
27
+ cur_spec = configurations[cur_rails_env]
28
+ table.establish_connection(cur_spec) unless table.connected?
29
+
30
+ if(new_rails_env.empty? or cur_rails_env == new_rails_env)
31
+ table.transaction{ block.call(table.connection) }
32
+ else
33
+ new_spec = configurations[new_rails_env]
34
+ table.establish_connection(new_spec)
35
+ Bj.rails_env = new_rails_env
36
+ begin
37
+ table.transaction{ block.call(table.connection) }
38
+ ensure
39
+ table.establish_connection(cur_spec)
40
+ Bj.rails_env = cur_rails_env
41
+ end
42
+ end
43
+ end
44
+
45
+ def chroot options = {}, &block
46
+ if defined? @chrooted and @chrooted
47
+ return(block ? block.call(@chrooted) : @chrooted)
48
+ end
49
+ if block
50
+ begin
51
+ chrooted = @chrooted
52
+ Dir.chdir(@chrooted = rails_root) do
53
+ raise RailsRoot, "<#{ Dir.pwd }> is not a rails root" unless Util.valid_rails_root?(Dir.pwd)
54
+ block.call(@chrooted)
55
+ end
56
+ ensure
57
+ @chrooted = chrooted
58
+ end
59
+ else
60
+ Dir.chdir(@chrooted = rails_root)
61
+ raise RailsRoot, "<#{ Dir.pwd }> is not a rails root" unless Util.valid_rails_root?(Dir.pwd)
62
+ @chrooted
63
+ end
64
+ end
65
+
66
+ def boot
67
+ load File.join(rails_root, "config", "boot.rb")
68
+ load File.join(rails_root, "config", "environment.rb")
69
+ end
70
+ end
71
+ send :extend, ClassMethods
72
+ end
@@ -0,0 +1,4 @@
1
+ class Bj
2
+ class Error < ::StandardError; end
3
+ class RailsRoot < Error; end
4
+ end
@@ -0,0 +1,112 @@
1
+ class Bj
2
+ class JobList < ::Array
3
+ module ClassMethods
4
+ def for jobs, options = {}
5
+ if Joblist === jobs
6
+ jobs.update options
7
+ return jobs
8
+ end
9
+ options.to_options!
10
+ jobs = [jobs].flatten.compact
11
+ list = []
12
+ jobs.each do |arg|
13
+ list.push(
14
+ case arg
15
+ when String
16
+ case arg
17
+ when %r/^\d+$/
18
+ job_from_id arg
19
+ else
20
+ job_from_string arg
21
+ end
22
+ when Hash
23
+ job_from_hash arg
24
+ when Io
25
+ jobs_from_io arg
26
+ when Fixnum, Bignum
27
+ job_from_number arg
28
+ else
29
+ job_from_string arg
30
+ end
31
+ )
32
+ end
33
+ list.flatten!
34
+ list.compact!
35
+ list.map!{|job| job.reverse_merge! options}
36
+ list
37
+ end
38
+
39
+ def job_from_hash arg
40
+ arg.to_hash.to_options!
41
+ end
42
+
43
+ def job_from_string arg
44
+ unless arg.strip.empty?
45
+ { :command => arg.to_s }
46
+ else
47
+ nil
48
+ end
49
+ end
50
+
51
+ def job_from_number arg
52
+ id = arg.to_i
53
+ Table::Job.find(id).to_hash
54
+ end
55
+
56
+ def jobs_from_io arg
57
+ if arg == "-"
58
+ load_from_io STDIN
59
+ else
60
+ if arg.respond_to? :read
61
+ load_from_io arg
62
+ else
63
+ open(arg, "r"){|fd| load_from_io fd}
64
+ end
65
+ end
66
+ end
67
+
68
+ def load_from_io io
69
+ list = []
70
+ io.each do |line|
71
+ line.strip!
72
+ next if line.empty?
73
+ list << job_from_string(line)
74
+ end
75
+ list
76
+ end
77
+
78
+ def jobs_from_yaml arg
79
+ object =
80
+ if arg == "-"
81
+ YAML.load STDIN
82
+ else
83
+ if arg.respond_to? :read
84
+ YAML.load arg
85
+ else
86
+ open(arg, "r"){|fd| YAML.load fd}
87
+ end
88
+ end
89
+ Joblist.for object
90
+ end
91
+ end
92
+ send :extend, ClassMethods
93
+
94
+ module InstanceMethods
95
+ def update options = {}
96
+ options.to_options!
97
+ each{|job| job.update options}
98
+ end
99
+
100
+ def push other
101
+ Joblist.for(other).each do |job|
102
+ super job
103
+ end
104
+ self
105
+ end
106
+ alias_method "<<", "push"
107
+ end
108
+ send :include, InstanceMethods
109
+ end
110
+
111
+ Joblist = JobList
112
+ end
@@ -0,0 +1,50 @@
1
+ class Bj
2
+ class Logger < ::Logger
3
+ def self.new *a, &b
4
+ super(*a, &b).instance_eval{ @default_formatter = @formatter = Formatter.new; self }
5
+ end
6
+ def format_message(severity, datetime, progname, msg)
7
+ (@formatter || @default_formatter).call(severity, datetime, progname, msg)
8
+ end
9
+
10
+ def device
11
+ @logdev.instance_eval{ @dev }
12
+ end
13
+
14
+ def tty?
15
+ device.respond_to?('tty?') and device.tty?
16
+ end
17
+
18
+ def turn which
19
+ @logdev.extend OnOff unless OnOff === @logdev
20
+ @logdev.turn which
21
+ end
22
+
23
+ module OnOff
24
+ def turn which
25
+ @turned = which.to_s =~ %r/on/i ? :on : :off
26
+ end
27
+
28
+ def write message
29
+ return message.to_s.size if @turned == :off
30
+ super
31
+ end
32
+ end
33
+
34
+ def on
35
+ turn :on
36
+ end
37
+ alias_method "on!", "on"
38
+ def self.on *a, &b
39
+ new(*a, &b).instance_eval{ turn :on; self }
40
+ end
41
+
42
+ def off
43
+ turn :off
44
+ end
45
+ alias_method "off!", "off"
46
+ def self.off *a, &b
47
+ new(*a, &b).instance_eval{ turn :off; self }
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,330 @@
1
+ class Bj
2
+ class Runner
3
+ class Background
4
+ def self.for(*a, &b) new(*a, &b) end
5
+
6
+ fattr("command"){}
7
+ fattr("thread"){}
8
+ fattr("pid"){}
9
+
10
+ def initialize command
11
+ @command = command
12
+ @thread = new_thread
13
+ end
14
+
15
+ def inspect
16
+ {
17
+ "command" => command,
18
+ "pid" => pid,
19
+ }.inspect
20
+ end
21
+
22
+
23
+ # TODO - auto start runner?
24
+
25
+ def new_thread
26
+ this = self
27
+ Thread.new do
28
+ Thread.current.abort_on_exception = true
29
+ loop do
30
+ cleanup = lambda{}
31
+
32
+ IO.popen command, "r+" do |pipe|
33
+ this.pid = pid = pipe.pid
34
+ cleanup = lambda do
35
+ cleanup = lambda{}
36
+ begin; Process.kill(Runner.kill_signal, pid); rescue Exception; 42; end
37
+ end
38
+ at_exit &cleanup
39
+ Process.wait
40
+ end
41
+
42
+ Bj.logger.error{ "#{ command } failed with #{ $?.inspect }" } unless
43
+ [0, 42].include?($?.exitstatus)
44
+
45
+ cleanup.call
46
+
47
+ sleep 42
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ module ClassMethods
54
+ fattr("thread"){ Thread.current }
55
+ fattr("hup_signal"){ Signal.list.keys.index("HUP") ? "HUP" : "ABRT" }
56
+ fattr("hup_signaled"){ false }
57
+ fattr("kill_signal"){ "TERM" }
58
+ fattr("kill_signaled"){ false }
59
+
60
+ def tickle
61
+ return nil if Bj.config[Runner.no_tickle_key]
62
+ ping or start
63
+ end
64
+
65
+ def ping
66
+ begin
67
+ pid = nil
68
+ uri = nil
69
+ process = nil
70
+ Bj.transaction do
71
+ pid = Bj.config[Runner.key(Process.pid)] || Bj.config[Runner.key]
72
+ uri = Bj.config["#{ pid }.uri"]
73
+ process =
74
+ if uri
75
+ require "drb"
76
+ # DRb.start_service "druby://localhost:0"
77
+ DRbObject.new(nil, uri)
78
+ else
79
+ Process
80
+ end
81
+ end
82
+ return nil unless pid
83
+ pid = Integer pid
84
+ begin
85
+ process.kill Runner.hup_signal, pid
86
+ pid
87
+ rescue Exception => e
88
+ false
89
+ end
90
+ rescue Exception => e
91
+ false
92
+ end
93
+ end
94
+
95
+ def key ppid = 0
96
+ ppid ||= 0
97
+ #"#{ Bj.rails_env }.#{ ppid }.pid"
98
+ "runner.#{ ppid }.pid"
99
+ end
100
+
101
+ def no_tickle_key
102
+ # "#{ Bj.rails_env }.no_tickle"
103
+ "no_tickle"
104
+ end
105
+
106
+ def start options = {}
107
+ options.to_options!
108
+ background.delete Bj.rails_env if options[:force]
109
+ background[Bj.rails_env] ||= Background.for(command)
110
+ end
111
+
112
+ def background
113
+ @background ||= Hash.new
114
+ end
115
+
116
+ def background= value
117
+ @background ||= value
118
+ end
119
+
120
+ def command
121
+ "#{ Bj.ruby } " + %W[
122
+ #{ Bj.script }
123
+ run
124
+ --forever
125
+ --redirect=#{ log }
126
+ --ppid=#{ Process.pid }
127
+ --rails_env=#{ Bj.rails_env }
128
+ --rails_root=#{ Bj.rails_root }
129
+ ].map{|word| word.inspect}.join(" ")
130
+ end
131
+
132
+ def log
133
+ File.join logdir, "bj.#{ Bj.hostname }.#{ Bj.rails_env }.log"
134
+ end
135
+
136
+ def logdir
137
+ File.join File.expand_path(Bj.rails_root), 'log'
138
+ end
139
+
140
+ def run options = {}, &block
141
+ new(options, &block).run
142
+ end
143
+ end
144
+ send :extend, ClassMethods
145
+
146
+ module Instance_Methods
147
+ fattr("options"){}
148
+ fattr("block"){}
149
+
150
+ def initialize options = {}, &block
151
+ options.to_options!
152
+ @options, @block = options, block
153
+ end
154
+
155
+ def run
156
+ wait = options[:wait] || 42
157
+ limit = options[:limit]
158
+ forever = options[:forever]
159
+
160
+ limit = false if forever
161
+ wait = Integer wait
162
+ loopno = 0
163
+
164
+ Runner.thread = Thread.current
165
+ Bj.chroot
166
+
167
+ register or exit!(EXIT::WARNING)
168
+
169
+ Bj.logger.info{ "STARTED" }
170
+ at_exit{ Bj.logger.info{ "STOPPED" } }
171
+
172
+ fill_morgue
173
+ install_signal_handlers
174
+
175
+ loop do
176
+ ping_parent
177
+
178
+ loopno += 1
179
+ break if(limit and loopno > limit)
180
+
181
+ archive_jobs
182
+
183
+ catch :no_jobs do
184
+ loop do
185
+ job = thread = stdout = stderr = nil
186
+
187
+ Bj.transaction(options) do
188
+ now = Time.now.utc
189
+
190
+ job = Bj::Table::Job.find :first,
191
+ :conditions => ["state = ? and submitted_at <= ?", "pending", now],
192
+ :order => "priority DESC, submitted_at ASC",
193
+ :limit => 1,
194
+ :lock => true
195
+ throw :no_jobs unless job
196
+
197
+ Bj.logger.info{ "#{ job.title } - starting..." }
198
+ end
199
+
200
+ job.run!
201
+
202
+ Bj.logger.info{ "#{ job.title } - exit_status=#{ job.exit_status }" }
203
+ end
204
+ end
205
+
206
+ Runner.hup_signaled false
207
+ wait.times do
208
+ break if Runner.hup_signaled?
209
+ break if Runner.kill_signaled?
210
+ sleep 1
211
+ end
212
+
213
+ break unless(limit or limit == false)
214
+ break if Runner.kill_signaled?
215
+ end
216
+ end
217
+
218
+ def ping_parent
219
+ ppid = options[:ppid]
220
+ return unless ppid
221
+ begin
222
+ Process.kill 0, Integer(ppid)
223
+ rescue Errno::ESRCH
224
+ Kernel.exit 42
225
+ rescue Exception
226
+ 42
227
+ end
228
+ end
229
+
230
+ def install_signal_handlers
231
+ Runner.hup_signaled false
232
+ hup_handler = nil
233
+ hup_handler =
234
+ trap Runner.hup_signal do |*a|
235
+ begin
236
+ Runner.hup_signaled true
237
+ rescue Exception => e
238
+ Bj.logger.error{ e } rescue nil
239
+ end
240
+ hup_handler.call *a rescue nil
241
+ end
242
+
243
+ Runner.kill_signaled false
244
+ kill_handler = nil
245
+ kill_handler =
246
+ trap Runner.kill_signal do |*a|
247
+ begin
248
+ Runner.kill_signaled true
249
+ rescue Exception => e
250
+ Bj.logger.error{ e } rescue nil
251
+ end
252
+ kill_handler.call *a rescue nil
253
+ end
254
+
255
+ begin
256
+ trap("INT"){ exit }
257
+ rescue Exception
258
+ end
259
+ end
260
+
261
+ def fill_morgue
262
+ Bj.transaction do
263
+ now = Time.now.utc
264
+ jobs = Bj::Table::Job.find :all,
265
+ :conditions => ["state = 'running' and runner = ?", Bj.hostname]
266
+ jobs.each do |job|
267
+ if job.is_restartable?
268
+ Bj.logger.info{ "#{ job.title } - found dead and bloated but resubmitted" }
269
+ %w[ runner pid started_at finished_at stdout stderr exit_status ].each do |column|
270
+ job[column] = nil
271
+ end
272
+ job.state = 'pending'
273
+ else
274
+ Bj.logger.info{ "#{ job.title } - found dead and bloated" }
275
+ job.state = 'dead'
276
+ job.finished_at = now
277
+ end
278
+ job.save!
279
+ end
280
+ end
281
+ end
282
+
283
+ def archive_jobs
284
+ Bj.transaction do
285
+ now = Time.now.utc
286
+ too_old = now - Bj.ttl
287
+ jobs = Bj::Table::Job.find :all,
288
+ :conditions => ["(state = 'finished' or state = 'dead') and submitted_at < ?", too_old]
289
+ jobs.each do |job|
290
+ Bj.logger.info{ "#{ job.title } - archived" }
291
+ hash = job.to_hash.update(:archived_at => now)
292
+ Bj::Table::JobArchive.create! hash
293
+ job.destroy
294
+ end
295
+ end
296
+ end
297
+
298
+ def register
299
+ Bj.transaction do
300
+ pid = Bj.config[key]
301
+ return false if Util.alive?(pid)
302
+ Bj.config[key] = Process.pid
303
+ unless Bj.util.ipc_signals_supported? # not winblows
304
+ require "drb"
305
+ DRb.start_service "druby://localhost:0", Process
306
+ Bj.config["#{ Process.pid }.uri"] = DRb.uri
307
+ end
308
+ end
309
+ at_exit{ unregister }
310
+ true
311
+ rescue Exception
312
+ false
313
+ end
314
+
315
+ def unregister
316
+ Bj.transaction do
317
+ Bj.config.delete key
318
+ end
319
+ true
320
+ rescue Exception
321
+ false
322
+ end
323
+
324
+ def key
325
+ @key ||= ( options[:ppid] ? Runner.key(options[:ppid]) : Runner.key )
326
+ end
327
+ end
328
+ send :include, Instance_Methods
329
+ end
330
+ end