bj_fixed_for_rails3 1.0.2

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.
data/lib/bj/table.rb ADDED
@@ -0,0 +1,384 @@
1
+ class Bj
2
+ #
3
+ # table base class
4
+ #
5
+ class Table < ActiveRecord::Base
6
+ module ClassMethods
7
+ attribute("list"){ Array.new }
8
+ attribute("migration"){}
9
+
10
+ def migration_code classname = "BjMigration"
11
+ <<-code
12
+ class #{ classname } < ActiveRecord::Migration
13
+ def self.up
14
+ Bj::Table.each{|table| table.up}
15
+ end
16
+ def self.down
17
+ Bj::Table.reverse_each{|table| table.down}
18
+ end
19
+ end
20
+ code
21
+ end
22
+
23
+ def up
24
+ migration_class.up
25
+ end
26
+
27
+ def down
28
+ migration_class.down
29
+ end
30
+
31
+ def migration_class
32
+ table = self
33
+ @migration_class ||=
34
+ Class.new(ActiveRecord::Migration) do
35
+ sc =
36
+ class << self
37
+ self
38
+ end
39
+ sc.module_eval{ attribute :table => table }
40
+ sc.module_eval &table.migration
41
+ end
42
+ end
43
+
44
+ def content_column_names
45
+ @content_column_names = content_columns.map{|column| column.name}
46
+ end
47
+
48
+ def create_hash_for options
49
+ options.to_options!
50
+ hash = {}
51
+ content_column_names.each do |key|
52
+ key = key.to_s.to_sym
53
+ hash[key] = options[key]
54
+ end
55
+ hash
56
+ end
57
+
58
+ def each *a, &b
59
+ list.each *a, &b
60
+ end
61
+
62
+ def reverse_each *a, &b
63
+ list.reverse.each *a, &b
64
+ end
65
+ end
66
+ send :extend, ClassMethods
67
+
68
+ module InstanceMethods
69
+ def to_hash
70
+ oh = OrderedHash.new
71
+ self.class.content_column_names.each{|c| oh[c] = self[c]}
72
+ oh
73
+ end
74
+ end
75
+ send :include, InstanceMethods
76
+
77
+ module RecursivelyInherited
78
+ def inherited other
79
+ super
80
+ ensure
81
+ (Table.list << other).uniq!
82
+ basename = other.name.split(%r/::/).last.underscore
83
+ Table.singleton_class{ attribute basename => other }
84
+ other.send :extend, RecursivelyInherited
85
+ end
86
+ end
87
+ send :extend, RecursivelyInherited
88
+
89
+ #
90
+ # table classes
91
+ #
92
+ class Job < Table
93
+ set_table_name "bj_job"
94
+ set_primary_key "#{ table_name }_id"
95
+
96
+ migration {
97
+ define_method :up do
98
+ create_table table.table_name, :primary_key => table.primary_key, :force => true do |t|
99
+ t.column "command" , :text
100
+
101
+ t.column "state" , :text
102
+ t.column "priority" , :integer
103
+ t.column "tag" , :text
104
+ t.column "is_restartable" , :integer
105
+
106
+ t.column "submitter" , :text
107
+ t.column "runner" , :text
108
+ t.column "pid" , :integer
109
+
110
+ t.column "submitted_at" , :datetime
111
+ t.column "started_at" , :datetime
112
+ t.column "finished_at" , :datetime
113
+
114
+ t.column "env" , :text
115
+ t.column "stdin" , :text
116
+ t.column "stdout" , :text
117
+ t.column "stderr" , :text
118
+ t.column "exit_status" , :integer
119
+ end
120
+ end
121
+
122
+ define_method :down do
123
+ drop_table table.table_name
124
+ end
125
+ }
126
+
127
+ module ClassMethods
128
+ def submit jobs, options = {}, &block
129
+ jobs = Joblist.for jobs, options
130
+ returned = []
131
+ transaction do
132
+ jobs.each do |job|
133
+ job = create_hash_for(job.reverse_merge(submit_defaults))
134
+ job = create! job
135
+ returned << (block ? block.call(job) : job)
136
+ end
137
+ end
138
+ returned
139
+ end
140
+
141
+ def submit_defaults
142
+ {
143
+ :state => "pending",
144
+ :priority => 0,
145
+ :tag => "",
146
+ :is_restartable => true,
147
+ :submitter => Bj.hostname,
148
+ :submitted_at => Time.now,
149
+ }
150
+ end
151
+ end
152
+ send :extend, ClassMethods
153
+
154
+ module InstanceMethods
155
+ def title
156
+ "job[#{ id }](#{ command })"
157
+ end
158
+ def finished
159
+ reload
160
+ exit_status
161
+ end
162
+ alias_method "finished?", "finished"
163
+ end
164
+ send :include, InstanceMethods
165
+ end
166
+
167
+ class JobArchive < Job
168
+ set_table_name "bj_job_archive"
169
+ set_primary_key "#{ table_name }_id"
170
+
171
+ migration {
172
+ define_method(:up) do
173
+ create_table table.table_name, :primary_key => table.primary_key, :force => true do |t|
174
+ t.column "command" , :text
175
+
176
+ t.column "state" , :text
177
+ t.column "priority" , :integer
178
+ t.column "tag" , :text
179
+ t.column "is_restartable" , :integer
180
+
181
+ t.column "submitter" , :text
182
+ t.column "runner" , :text
183
+ t.column "pid" , :integer
184
+
185
+ t.column "submitted_at" , :datetime
186
+ t.column "started_at" , :datetime
187
+ t.column "finished_at" , :datetime
188
+ t.column "archived_at" , :datetime
189
+
190
+ t.column "env" , :text
191
+ t.column "stdin" , :text
192
+ t.column "stdout" , :text
193
+ t.column "stderr" , :text
194
+ t.column "exit_status" , :integer
195
+ end
196
+ end
197
+
198
+ define_method(:down) do
199
+ drop_table table.table_name
200
+ end
201
+ }
202
+ end
203
+
204
+ # TODO - initialize with a set of global defaults and fallback to those on perhaps '* * key'
205
+ class Config < Table
206
+ set_table_name "bj_config"
207
+ set_primary_key "#{ table_name }_id"
208
+
209
+ migration {
210
+ define_method(:up) do
211
+ create_table table.table_name, :primary_key => table.primary_key, :force => true do |t|
212
+ t.column "hostname" , :text
213
+ t.column "key" , :text
214
+ t.column "value" , :text
215
+ t.column "cast" , :text
216
+ end
217
+
218
+ begin
219
+ add_index table.table_name, %w[ hostname key ], :unique => true
220
+ rescue Exception
221
+ STDERR.puts "WARNING: your database does not support unique indexes on text fields!?"
222
+ end
223
+ end
224
+
225
+ define_method(:down) do
226
+ begin
227
+ remove_index table.table_name, :column => %w[ hostname key ]
228
+ rescue Exception
229
+ end
230
+ drop_table table.table_name
231
+ end
232
+ }
233
+
234
+ module ClassMethods
235
+ def [] key
236
+ get key
237
+ end
238
+
239
+ def get key, options = {}
240
+ transaction do
241
+ options.to_options!
242
+ hostname = options[:hostname] || Bj.hostname
243
+ record = find :first, :conditions => conditions(:key => key, :hostname => hostname)
244
+ record ? record.value : default_for(key)
245
+ end
246
+ end
247
+
248
+ def conditions options = {}
249
+ options.to_options!
250
+ options.reverse_merge!(
251
+ :hostname => Bj.hostname
252
+ )
253
+ options
254
+ end
255
+
256
+ def default_for key
257
+ record = find :first, :conditions => conditions(:key => key, :hostname => '*')
258
+ record ? record.value : nil
259
+ end
260
+
261
+ def []= key, value
262
+ set key, value
263
+ end
264
+
265
+ def set key, value, options = {}
266
+ transaction do
267
+ options.to_options!
268
+ hostname = options[:hostname] || Bj.hostname
269
+ record = find :first, :conditions => conditions(:key => key, :hostname => hostname), :lock => true
270
+ cast = options[:cast] || cast_for(value)
271
+ key = key.to_s
272
+ value = value.to_s
273
+ if record
274
+ record["value"] = value
275
+ record["cast"] = cast
276
+ record.save!
277
+ else
278
+ create! :hostname => hostname, :key => key, :value => value, :cast => cast
279
+ end
280
+ value
281
+ end
282
+ end
283
+
284
+ def delete key
285
+ transaction do
286
+ record = find :first, :conditions => conditions(:key => key), :lock => true
287
+ if record
288
+ record.destroy
289
+ record
290
+ else
291
+ nil
292
+ end
293
+ end
294
+ end
295
+
296
+ def has_key? key
297
+ record = find :first, :conditions => conditions(:key => key)
298
+ record ? record : false
299
+ end
300
+ alias_method "has_key", "has_key?"
301
+
302
+ def keys
303
+ find(:all, :conditions => conditions).map(&:key)
304
+ end
305
+
306
+ def values
307
+ find(:all, :conditions => conditions).map(&:value)
308
+ end
309
+
310
+ def for options = {}
311
+ oh = OrderedHash.new
312
+ find(:all, :conditions => conditions(options)).each do |record|
313
+ oh[record.key] = record.value
314
+ end
315
+ oh
316
+ end
317
+
318
+ def cast_for value
319
+ case value
320
+ when TrueClass, FalseClass
321
+ 'to_bool'
322
+ when NilClass
323
+ 'to_nil'
324
+ when Fixnum, Bignum
325
+ 'to_i'
326
+ when Float
327
+ 'to_f'
328
+ when Time
329
+ 'to_time'
330
+ when Symbol
331
+ 'to_sym'
332
+ else
333
+ case value.to_s
334
+ when %r/^\d+$/
335
+ 'to_i'
336
+ when %r/^\d+\.\d+$/
337
+ 'to_f'
338
+ when %r/^nil$|^$/
339
+ 'to_nil'
340
+ when %r/^true|false$/
341
+ 'to_bool'
342
+ else
343
+ 'to_s'
344
+ end
345
+ end
346
+ end
347
+
348
+ def casts
349
+ @casts ||= {
350
+ 'to_bool' => lambda do |value|
351
+ value.to_s =~ %r/^true$/i ? true : false
352
+ end,
353
+ 'to_i' => lambda do |value|
354
+ Integer value.to_s.gsub(%r/^(-)?0*/,'\1')
355
+ end,
356
+ 'to_f' => lambda do |value|
357
+ Float value.to_s.gsub(%r/^0*/,'')
358
+ end,
359
+ 'to_time' => lambda do |value|
360
+ Time.parse(value.to_s)
361
+ end,
362
+ 'to_sym' => lambda do |value|
363
+ value.to_s.to_sym
364
+ end,
365
+ 'to_nil' => lambda do |value|
366
+ value.to_s =~ %r/^nil$|^$/i ? nil : value.to_s
367
+ end,
368
+ 'to_s' => lambda do |value|
369
+ value.to_s
370
+ end,
371
+ }
372
+ end
373
+ end
374
+ send :extend, ClassMethods
375
+
376
+ module InstanceMethods
377
+ def value
378
+ self.class.casts[cast][self["value"]]
379
+ end
380
+ end
381
+ send :include, InstanceMethods
382
+ end
383
+ end
384
+ end
data/lib/bj/util.rb ADDED
@@ -0,0 +1,111 @@
1
+ class Bj
2
+ module Util
3
+ module ModuleMethods
4
+ def constant_get const, &block
5
+ begin
6
+ ancestors = const.split(%r/::/)
7
+ parent = Object
8
+ while((child = ancestors.shift))
9
+ klass = parent.const_get child
10
+ parent = klass
11
+ end
12
+ klass
13
+ rescue
14
+ block ? block.call : raise
15
+ end
16
+ end
17
+
18
+ def const_or_env const, &block
19
+ constant_get(const){ ENV[const] || block.call }
20
+ end
21
+
22
+ def spawn cmd, options = {}
23
+ options.to_options!
24
+ logger = options.has_key?(:logger) ? options[:logger] : Bj.logger
25
+ logger.info{ "cmd <#{ cmd }>" } if logger
26
+ status = systemu cmd, 1=>(stdout=""), 2=>(stderr="")
27
+ logger.info{ "status <#{ status.exitstatus }>" } if logger
28
+ status.exitstatus.zero? or raise "#{ cmd.inspect } failed with #{ $?.inspect }"
29
+ [ stdout, stderr ]
30
+ end
31
+
32
+ def start *a
33
+ q = Queue.new
34
+ thread = Thread.new do
35
+ Thread.current.abort_on_exception = true
36
+ systemu(*a){|pid| q << pid}
37
+ end
38
+ pid = q.pop
39
+ thread.singleton_class{ define_method(:pid){ pid } }
40
+ thread
41
+ end
42
+
43
+ def alive pid
44
+ return false unless pid
45
+ pid = Integer pid.to_s
46
+ Process::kill 0, pid
47
+ true
48
+ rescue Errno::ESRCH, Errno::EPERM
49
+ false
50
+ end
51
+ alias_method "alive?", "alive"
52
+
53
+ def which_ruby
54
+ c = ::Config::CONFIG
55
+ ruby = File::join(c['bindir'], c['ruby_install_name']) << c['EXEEXT']
56
+ raise "ruby @ #{ ruby } not executable!?" unless test(?e, ruby)
57
+ ruby
58
+ end
59
+
60
+ def which_rake
61
+ tmp = Tempfile.new Process.pid
62
+ tmp.write "task(:foobar){ puts 42 }"
63
+ tmp.close
64
+ bat = spawn("rake.bat -f #{ tmp.path.inspect } foobar", :logger => false) rescue false
65
+ bat ? "rake.bat" : "rake"
66
+ ensure
67
+ tmp.close! rescue nil
68
+ end
69
+
70
+ def ipc_signals_supported
71
+ @ipc_signals_supported ||=
72
+ IO.popen 'ruby', 'r+' do |ruby|
73
+ pid = ruby.pid
74
+ begin
75
+ Process.kill 'TERM', pid
76
+ true
77
+ rescue Exception
78
+ false
79
+ end
80
+ end
81
+ end
82
+ alias_method "ipc_signals_supported?", "ipc_signals_supported"
83
+
84
+ def find_script basename
85
+ path = ENV["PATH"] || ENV["path"] || Bj.default_path
86
+ raise "no env PATH" unless path
87
+ path = path.split File::PATH_SEPARATOR
88
+ path.unshift File.join(Bj.rails_root, "script")
89
+ path.each do |directory|
90
+ script = File.join directory, basename
91
+ return File.expand_path(script) if(test(?s, script) and test(?r, script))
92
+ end
93
+ raise "no #{ basename } found in #{ path.inspect }"
94
+ end
95
+
96
+ def valid_rails_root root = ".", expected = %w[ config script app ]
97
+ directories = expected.flatten.compact.map{|dir| dir.to_s}
98
+ directories.all?{|dir| test(?d, File.join(root, dir))}
99
+ end
100
+ alias_method "valid_rails_root?", "valid_rails_root"
101
+
102
+ def emsg e
103
+ m = e.message rescue ""
104
+ c = e.class rescue Exception
105
+ b = e.backtrace.join("\n") rescue ""
106
+ "#{ m }(#{ c })\n#{ b }"
107
+ end
108
+ end
109
+ send :extend, ModuleMethods
110
+ end
111
+ end
data/lib/bj.rb ADDED
@@ -0,0 +1,88 @@
1
+ unless defined? Bj
2
+ class Bj
3
+ #
4
+ # constants and associated attrs
5
+ #
6
+ Bj::VERSION = "1.0.1" #unless defined? Bj::VERSION
7
+ def self.version() Bj::VERSION end
8
+
9
+ Bj::LIBDIR = File.expand_path(File::join(File.dirname(__FILE__), "bj")) + File::SEPARATOR unless
10
+ defined? Bj::LIBDIR
11
+ def self.libdir(*value)
12
+ unless value.empty?
13
+ File.join libdir, *value
14
+ else
15
+ Bj::LIBDIR
16
+ end
17
+ end
18
+
19
+ module EXIT
20
+ SUCCESS = 0
21
+ FAILURE = 1
22
+ WARNING = 42
23
+ end
24
+ #
25
+ # built-in
26
+ #
27
+ require "socket"
28
+ require "yaml"
29
+ require "thread"
30
+ require "rbconfig"
31
+ require "set"
32
+ require "erb"
33
+ require "tempfile"
34
+ require "logger"
35
+ #
36
+ # bootstrap rubygems
37
+ #
38
+ begin
39
+ require "rubygems"
40
+ rescue LoadError
41
+ 42
42
+ end
43
+ #
44
+ # rubyforge/remote
45
+ #
46
+ require "active_record"
47
+ #
48
+ # rubyforge/remote or local/lib
49
+ #
50
+ #%w[ attributes systemu orderedhash ].each do |lib|
51
+ %w[ systemu orderedhash ].each do |lib|
52
+ begin
53
+ require lib
54
+ rescue
55
+ require libdir(lib)
56
+ end
57
+ end
58
+ #
59
+ # local
60
+ #
61
+ load libdir("attributes.rb")
62
+ load libdir("stdext.rb")
63
+ load libdir("util.rb")
64
+ load libdir("errors.rb")
65
+ load libdir("logger.rb")
66
+ load libdir("bj.rb")
67
+ load libdir("joblist.rb")
68
+ load libdir("table.rb")
69
+ load libdir("runner.rb")
70
+ load libdir("api.rb")
71
+ #
72
+ # an imperfect reloading hook - because neither rails' plugins nor gems provide one, sigh...
73
+ #
74
+ def self.reload!
75
+ background = nil
76
+ ::Object.module_eval do
77
+ background = Bj.runner.background
78
+ remove_const :Bj rescue nil
79
+ remove_const :BackgroundJob rescue nil
80
+ end
81
+ returned = load __FILE__ rescue nil
82
+ Bj.runner.background = background if background
83
+ returned
84
+ end
85
+ end
86
+
87
+ BackgroundJob = Bj
88
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bj_fixed_for_rails3
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 2
10
+ version: 1.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Ara T. Howard
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-15 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: main
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 2
32
+ - 6
33
+ - 0
34
+ version: 2.6.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: systemu
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 31
46
+ segments:
47
+ - 1
48
+ - 2
49
+ - 0
50
+ version: 1.2.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: orderedhash
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 25
62
+ segments:
63
+ - 0
64
+ - 0
65
+ - 3
66
+ version: 0.0.3
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ description:
70
+ email: ara.t.howard@gmail.com
71
+ executables:
72
+ - bj
73
+ extensions: []
74
+
75
+ extra_rdoc_files: []
76
+
77
+ files:
78
+ - bin/bj
79
+ - bj-1.0.2.gem
80
+ - gemspec.rb
81
+ - HISTORY
82
+ - install.rb
83
+ - lib/bj/api.rb
84
+ - lib/bj/attributes.rb
85
+ - lib/bj/bj.rb
86
+ - lib/bj/errors.rb
87
+ - lib/bj/joblist.rb
88
+ - lib/bj/logger.rb
89
+ - lib/bj/runner.rb
90
+ - lib/bj/stdext.rb
91
+ - lib/bj/table.rb
92
+ - lib/bj/util.rb
93
+ - lib/bj.rb
94
+ - README
95
+ - TODO
96
+ has_rdoc: true
97
+ homepage: http://codeforpeople.com/lib/ruby/bj_fixed_for_rails3/
98
+ licenses: []
99
+
100
+ post_install_message:
101
+ rdoc_options: []
102
+
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ hash: 3
111
+ segments:
112
+ - 0
113
+ version: "0"
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ hash: 3
120
+ segments:
121
+ - 0
122
+ version: "0"
123
+ requirements: []
124
+
125
+ rubyforge_project: codeforpeople
126
+ rubygems_version: 1.3.7
127
+ signing_key:
128
+ specification_version: 3
129
+ summary: bj_fixed_for_rails3
130
+ test_files: []
131
+