ThiagoLelis-backgroundjob 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +7 -62
- data/README +63 -229
- data/Rakefile +22 -0
- data/background.gemspec +18 -0
- data/init.rb +33 -0
- data/install.rb +85 -200
- data/lib/arrayfields.rb +435 -0
- data/lib/attributes.rb +118 -0
- data/lib/bj.rb +1 -1
- data/lib/bj/runner.rb +7 -7
- data/lib/bj/table.rb +45 -25
- data/lib/bj/util.rb +4 -0
- data/lib/fattr.rb +153 -0
- data/lib/main.rb +60 -0
- data/lib/main/base.rb +515 -0
- data/lib/main/cast.rb +100 -0
- data/lib/main/factories.rb +20 -0
- data/lib/main/getoptlong.rb +470 -0
- data/lib/main/logger.rb +51 -0
- data/lib/main/mode.rb +42 -0
- data/lib/main/parameter.rb +685 -0
- data/lib/main/softspoken.rb +12 -0
- data/lib/main/stdext.rb +38 -0
- data/lib/main/usage.rb +211 -0
- data/lib/main/util.rb +91 -0
- data/lib/orderedautohash.rb +25 -0
- data/lib/orderedhash.rb +189 -0
- data/lib/systemu.rb +299 -0
- data/script/bj +55 -0
- data/tasks/bj_tasks.rake +4 -0
- data/test/bj_test.rb +8 -0
- data/uninstall.rb +1 -0
- metadata +44 -14
- data/TODO +0 -40
- data/rakefile +0 -3
data/lib/attributes.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
module Attributes
|
2
|
+
Attributes::VERSION = '5.0.0' unless defined? Attributes::VERSION
|
3
|
+
def self.version() Attributes::VERSION end
|
4
|
+
|
5
|
+
class List < ::Array
|
6
|
+
def << element
|
7
|
+
super
|
8
|
+
self
|
9
|
+
ensure
|
10
|
+
uniq!
|
11
|
+
index!
|
12
|
+
end
|
13
|
+
def index!
|
14
|
+
@index ||= Hash.new
|
15
|
+
each{|element| @index[element] = true}
|
16
|
+
end
|
17
|
+
def include? element
|
18
|
+
@index ||= Hash.new
|
19
|
+
@index[element] ? true : false
|
20
|
+
end
|
21
|
+
def initializers
|
22
|
+
@initializers ||= Hash.new
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def attributes *a, &b
|
27
|
+
unless a.empty?
|
28
|
+
returned = Hash.new
|
29
|
+
|
30
|
+
hashes, names = a.partition{|x| Hash === x}
|
31
|
+
names_and_defaults = {}
|
32
|
+
hashes.each{|h| names_and_defaults.update h}
|
33
|
+
names.flatten.compact.each{|name| names_and_defaults.update name => nil}
|
34
|
+
|
35
|
+
initializers = __attributes__.initializers
|
36
|
+
|
37
|
+
names_and_defaults.each do |name, default|
|
38
|
+
raise NameError, "bad instance variable name '@#{ name }'" if "@#{ name }" =~ %r/[!?=]$/o
|
39
|
+
name = name.to_s
|
40
|
+
|
41
|
+
initialize = b || lambda { default }
|
42
|
+
initializer = lambda do |this|
|
43
|
+
Object.instance_method('instance_eval').bind(this).call &initialize
|
44
|
+
end
|
45
|
+
initializer_id = initializer.object_id
|
46
|
+
__attributes__.initializers[name] = initializer
|
47
|
+
|
48
|
+
module_eval <<-code
|
49
|
+
def #{ name }=(*value, &block)
|
50
|
+
value.unshift block if block
|
51
|
+
@#{ name } = value.first
|
52
|
+
end
|
53
|
+
code
|
54
|
+
|
55
|
+
module_eval <<-code
|
56
|
+
def #{ name }(*value, &block)
|
57
|
+
value.unshift block if block
|
58
|
+
return self.send('#{ name }=', value.first) unless value.empty?
|
59
|
+
#{ name }! unless defined? @#{ name }
|
60
|
+
@#{ name }
|
61
|
+
end
|
62
|
+
code
|
63
|
+
|
64
|
+
module_eval <<-code
|
65
|
+
def #{ name }!
|
66
|
+
initializer = ObjectSpace._id2ref #{ initializer_id }
|
67
|
+
self.#{ name } = initializer.call(self)
|
68
|
+
@#{ name }
|
69
|
+
end
|
70
|
+
code
|
71
|
+
|
72
|
+
module_eval <<-code
|
73
|
+
def #{ name }?
|
74
|
+
#{ name }
|
75
|
+
end
|
76
|
+
code
|
77
|
+
|
78
|
+
attributes << name
|
79
|
+
returned[name] = initializer
|
80
|
+
end
|
81
|
+
|
82
|
+
returned
|
83
|
+
else
|
84
|
+
begin
|
85
|
+
__attribute_list__
|
86
|
+
rescue NameError
|
87
|
+
singleton_class =
|
88
|
+
class << self
|
89
|
+
self
|
90
|
+
end
|
91
|
+
klass = self
|
92
|
+
singleton_class.module_eval do
|
93
|
+
attribute_list = List.new
|
94
|
+
define_method('attribute_list'){ klass == self ? attribute_list : raise(NameError) }
|
95
|
+
alias_method '__attribute_list__', 'attribute_list'
|
96
|
+
end
|
97
|
+
__attribute_list__
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
%w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
|
103
|
+
end
|
104
|
+
|
105
|
+
class Object
|
106
|
+
def attributes *a, &b
|
107
|
+
sc =
|
108
|
+
class << self
|
109
|
+
self
|
110
|
+
end
|
111
|
+
sc.attributes *a, &b
|
112
|
+
end
|
113
|
+
%w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
|
114
|
+
end
|
115
|
+
|
116
|
+
class Module
|
117
|
+
include Attributes
|
118
|
+
end
|
data/lib/bj.rb
CHANGED
@@ -3,7 +3,7 @@ unless defined? Bj
|
|
3
3
|
#
|
4
4
|
# constants and associated attrs
|
5
5
|
#
|
6
|
-
Bj::VERSION = "1.0.
|
6
|
+
Bj::VERSION = "1.0.4" #unless defined? Bj::VERSION
|
7
7
|
def self.version() Bj::VERSION end
|
8
8
|
|
9
9
|
Bj::LIBDIR = File.expand_path(File::join(File.dirname(__FILE__), "bj")) + File::SEPARATOR unless
|
data/lib/bj/runner.rb
CHANGED
@@ -183,13 +183,13 @@ class Bj
|
|
183
183
|
job = thread = stdout = stderr = nil
|
184
184
|
|
185
185
|
Bj.transaction(options) do
|
186
|
-
now =
|
186
|
+
now = Util.now
|
187
187
|
|
188
|
-
job = Bj::Table::Job.
|
188
|
+
job = Bj::Table::Job.find_first_and_lock(
|
189
189
|
:conditions => ["state = ? and submitted_at <= ?", "pending", now],
|
190
190
|
:order => "priority DESC, submitted_at ASC",
|
191
191
|
:limit => 1,
|
192
|
-
:lock => true
|
192
|
+
:lock => true)
|
193
193
|
throw :no_jobs unless job
|
194
194
|
|
195
195
|
|
@@ -200,7 +200,7 @@ class Bj
|
|
200
200
|
stdin = job.stdin || ''
|
201
201
|
stdout = job.stdout || ''
|
202
202
|
stderr = job.stderr || ''
|
203
|
-
started_at =
|
203
|
+
started_at = Util.now
|
204
204
|
|
205
205
|
thread = Util.start command, :cwd=>Bj.rails_root, :env=>env, :stdin=>stdin, :stdout=>stdout, :stderr=>stderr
|
206
206
|
|
@@ -213,7 +213,7 @@ class Bj
|
|
213
213
|
end
|
214
214
|
|
215
215
|
exit_status = thread.value
|
216
|
-
finished_at =
|
216
|
+
finished_at = Util.now
|
217
217
|
|
218
218
|
Bj.transaction(options) do
|
219
219
|
job = Bj::Table::Job.find job.id
|
@@ -287,7 +287,7 @@ class Bj
|
|
287
287
|
|
288
288
|
def fill_morgue
|
289
289
|
Bj.transaction do
|
290
|
-
now =
|
290
|
+
now = Util.now
|
291
291
|
jobs = Bj::Table::Job.find :all,
|
292
292
|
:conditions => ["state = 'running' and runner = ?", Bj.hostname]
|
293
293
|
jobs.each do |job|
|
@@ -309,7 +309,7 @@ class Bj
|
|
309
309
|
|
310
310
|
def archive_jobs
|
311
311
|
Bj.transaction do
|
312
|
-
now =
|
312
|
+
now = Util.now
|
313
313
|
too_old = now - Bj.ttl
|
314
314
|
jobs = Bj::Table::Job.find :all,
|
315
315
|
:conditions => ["(state = 'finished' or state = 'dead') and submitted_at < ?", too_old]
|
data/lib/bj/table.rb
CHANGED
@@ -62,6 +62,24 @@ class Bj
|
|
62
62
|
def reverse_each *a, &b
|
63
63
|
list.reverse.each *a, &b
|
64
64
|
end
|
65
|
+
|
66
|
+
# find(:first, :lock => true) does not work in oracle because
|
67
|
+
# of the implicit usage of :limit. instead we have to find :all
|
68
|
+
# and grab the first element returned. this is okay because the
|
69
|
+
# conditions supplied to the find will return a small result set,
|
70
|
+
# thus minimizing superfluous row locks.
|
71
|
+
def find_first_and_lock(options = {})
|
72
|
+
options[:lock] = true
|
73
|
+
db_config = configurations[Bj.rails_env.to_s]
|
74
|
+
case db_config['adapter']
|
75
|
+
when 'oracle','oci'
|
76
|
+
options.delete(:limit)
|
77
|
+
find(:all, options).first
|
78
|
+
else
|
79
|
+
find(:first, options)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
65
83
|
end
|
66
84
|
send :extend, ClassMethods
|
67
85
|
|
@@ -96,25 +114,26 @@ class Bj
|
|
96
114
|
migration {
|
97
115
|
define_method :up do
|
98
116
|
create_table table.table_name, :primary_key => table.primary_key, :force => true do |t|
|
99
|
-
t.column "command" , :text
|
100
117
|
|
101
|
-
t.column "
|
118
|
+
t.column "command" , :string, :limit => 2000
|
119
|
+
|
120
|
+
t.column "state" , :string, :limit => 255
|
102
121
|
t.column "priority" , :integer
|
103
|
-
t.column "tag" , :
|
122
|
+
t.column "tag" , :string, :limit => 1000
|
104
123
|
t.column "is_restartable" , :integer
|
105
124
|
|
106
|
-
t.column "submitter" , :
|
107
|
-
t.column "runner" , :
|
125
|
+
t.column "submitter" , :string, :limit => 255
|
126
|
+
t.column "runner" , :string, :limit => 255
|
108
127
|
t.column "pid" , :integer
|
109
128
|
|
110
129
|
t.column "submitted_at" , :datetime
|
111
130
|
t.column "started_at" , :datetime
|
112
131
|
t.column "finished_at" , :datetime
|
113
132
|
|
114
|
-
t.column "env" , :
|
115
|
-
t.column "stdin" , :
|
116
|
-
t.column "stdout" , :
|
117
|
-
t.column "stderr" , :
|
133
|
+
t.column "env" , :string, :limit => 4000
|
134
|
+
t.column "stdin" , :string, :limit => 4000
|
135
|
+
t.column "stdout" , :string, :limit => 4000
|
136
|
+
t.column "stderr" , :string, :limit => 4000
|
118
137
|
t.column "exit_status" , :integer
|
119
138
|
end
|
120
139
|
end
|
@@ -145,9 +164,10 @@ class Bj
|
|
145
164
|
:tag => "",
|
146
165
|
:is_restartable => true,
|
147
166
|
:submitter => Bj.hostname,
|
148
|
-
:submitted_at => Time.now
|
167
|
+
:submitted_at => Time.now
|
149
168
|
}
|
150
169
|
end
|
170
|
+
|
151
171
|
end
|
152
172
|
send :extend, ClassMethods
|
153
173
|
|
@@ -171,15 +191,15 @@ class Bj
|
|
171
191
|
migration {
|
172
192
|
define_method(:up) do
|
173
193
|
create_table table.table_name, :primary_key => table.primary_key, :force => true do |t|
|
174
|
-
t.column "command" , :
|
194
|
+
t.column "command" , :string, :limit => 2000
|
175
195
|
|
176
|
-
t.column "state" , :
|
196
|
+
t.column "state" , :string, :limit => 255
|
177
197
|
t.column "priority" , :integer
|
178
|
-
t.column "tag" , :
|
198
|
+
t.column "tag" , :string, :limit => 1000
|
179
199
|
t.column "is_restartable" , :integer
|
180
200
|
|
181
|
-
t.column "submitter" , :
|
182
|
-
t.column "runner" , :
|
201
|
+
t.column "submitter" , :string, :limit => 255
|
202
|
+
t.column "runner" , :string, :limit => 255
|
183
203
|
t.column "pid" , :integer
|
184
204
|
|
185
205
|
t.column "submitted_at" , :datetime
|
@@ -187,10 +207,10 @@ class Bj
|
|
187
207
|
t.column "finished_at" , :datetime
|
188
208
|
t.column "archived_at" , :datetime
|
189
209
|
|
190
|
-
t.column "env" , :
|
191
|
-
t.column "stdin" , :
|
192
|
-
t.column "stdout" , :
|
193
|
-
t.column "stderr" , :
|
210
|
+
t.column "env" , :string, :limit => 4000
|
211
|
+
t.column "stdin" , :string, :limit => 4000
|
212
|
+
t.column "stdout" , :string, :limit => 4000
|
213
|
+
t.column "stderr" , :string, :limit => 4000
|
194
214
|
t.column "exit_status" , :integer
|
195
215
|
end
|
196
216
|
end
|
@@ -209,10 +229,10 @@ class Bj
|
|
209
229
|
migration {
|
210
230
|
define_method(:up) do
|
211
231
|
create_table table.table_name, :primary_key => table.primary_key, :force => true do |t|
|
212
|
-
t.column "hostname" , :
|
213
|
-
t.column "key" , :
|
214
|
-
t.column "value" , :
|
215
|
-
t.column "cast" , :
|
232
|
+
t.column "hostname" , :string, :limit => 255
|
233
|
+
t.column "key" , :string, :limit => 255
|
234
|
+
t.column "value" , :string, :limit => 4000
|
235
|
+
t.column "cast" , :string, :limit => 255
|
216
236
|
end
|
217
237
|
|
218
238
|
begin
|
@@ -266,7 +286,7 @@ class Bj
|
|
266
286
|
transaction do
|
267
287
|
options.to_options!
|
268
288
|
hostname = options[:hostname] || Bj.hostname
|
269
|
-
record =
|
289
|
+
record = find_first_and_lock :conditions => conditions(:key => key, :hostname => hostname), :lock => true
|
270
290
|
cast = options[:cast] || cast_for(value)
|
271
291
|
key = key.to_s
|
272
292
|
value = value.to_s
|
@@ -283,7 +303,7 @@ class Bj
|
|
283
303
|
|
284
304
|
def delete key
|
285
305
|
transaction do
|
286
|
-
record =
|
306
|
+
record = find_first_and_lock :conditions => conditions(:key => key), :lock => true
|
287
307
|
if record
|
288
308
|
record.destroy
|
289
309
|
record
|
data/lib/bj/util.rb
CHANGED
data/lib/fattr.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
module Fattr
|
2
|
+
Fattr::VERSION = '1.0.3' unless Fattr.const_defined?(:VERSION)
|
3
|
+
def self.version() Fattr::VERSION end
|
4
|
+
|
5
|
+
class List < ::Array
|
6
|
+
def << element
|
7
|
+
super
|
8
|
+
self
|
9
|
+
ensure
|
10
|
+
uniq!
|
11
|
+
index!
|
12
|
+
end
|
13
|
+
|
14
|
+
def index!
|
15
|
+
@index ||= Hash.new
|
16
|
+
each{|element| @index[element] = true}
|
17
|
+
end
|
18
|
+
|
19
|
+
def include? element
|
20
|
+
@index ||= Hash.new
|
21
|
+
@index[element] ? true : false
|
22
|
+
end
|
23
|
+
|
24
|
+
def initializers
|
25
|
+
@initializers ||= Hash.new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def fattrs *a, &b
|
30
|
+
unless a.empty?
|
31
|
+
returned = Hash.new
|
32
|
+
|
33
|
+
hashes, names = a.partition{|x| Hash === x}
|
34
|
+
names_and_defaults = {}
|
35
|
+
hashes.each{|h| names_and_defaults.update h}
|
36
|
+
names.flatten.compact.each{|name| names_and_defaults.update name => nil}
|
37
|
+
|
38
|
+
initializers = __fattrs__.initializers
|
39
|
+
|
40
|
+
names_and_defaults.each do |name, default|
|
41
|
+
raise NameError, "bad instance variable name '@#{ name }'" if "@#{ name }" =~ %r/[!?=]$/o
|
42
|
+
name = name.to_s
|
43
|
+
|
44
|
+
initialize = b || lambda { default }
|
45
|
+
initializer = lambda do |this|
|
46
|
+
Object.instance_method('instance_eval').bind(this).call &initialize
|
47
|
+
end
|
48
|
+
initializer_id = initializer.object_id
|
49
|
+
__fattrs__.initializers[name] = initializer
|
50
|
+
|
51
|
+
compile = lambda do |code|
|
52
|
+
begin
|
53
|
+
module_eval code
|
54
|
+
rescue SyntaxError
|
55
|
+
raise SyntaxError, "\n#{ code }\n"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# setter, block invocation caches block
|
60
|
+
code = <<-code
|
61
|
+
def #{ name }=(*value, &block)
|
62
|
+
value.unshift block if block
|
63
|
+
@#{ name } = value.first
|
64
|
+
end
|
65
|
+
code
|
66
|
+
compile[code]
|
67
|
+
|
68
|
+
# getter, providing a value or block causes it to acts as setter
|
69
|
+
code = <<-code
|
70
|
+
def #{ name }(*value, &block)
|
71
|
+
value.unshift block if block
|
72
|
+
return self.send('#{ name }=', value.first) unless value.empty?
|
73
|
+
#{ name }! unless defined? @#{ name }
|
74
|
+
@#{ name }
|
75
|
+
end
|
76
|
+
code
|
77
|
+
compile[code]
|
78
|
+
|
79
|
+
# bang method re-calls any initializer given at declaration time
|
80
|
+
code = <<-code
|
81
|
+
def #{ name }!
|
82
|
+
initializer = ObjectSpace._id2ref #{ initializer_id }
|
83
|
+
self.#{ name } = initializer.call(self)
|
84
|
+
@#{ name }
|
85
|
+
end
|
86
|
+
code
|
87
|
+
compile[code]
|
88
|
+
|
89
|
+
# query simply defers to getter - cast to bool
|
90
|
+
code = <<-code
|
91
|
+
def #{ name }?
|
92
|
+
self.#{ name }
|
93
|
+
end
|
94
|
+
code
|
95
|
+
compile[code]
|
96
|
+
|
97
|
+
fattrs << name
|
98
|
+
returned[name] = initializer
|
99
|
+
end
|
100
|
+
|
101
|
+
returned
|
102
|
+
else
|
103
|
+
begin
|
104
|
+
__fattr_list__
|
105
|
+
rescue NameError
|
106
|
+
singleton_class =
|
107
|
+
class << self
|
108
|
+
self
|
109
|
+
end
|
110
|
+
klass = self
|
111
|
+
singleton_class.module_eval do
|
112
|
+
fattr_list = List.new
|
113
|
+
define_method('fattr_list'){ klass == self ? fattr_list : raise(NameError) }
|
114
|
+
alias_method '__fattr_list__', 'fattr_list'
|
115
|
+
end
|
116
|
+
__fattr_list__
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
%w( __fattrs__ __fattr__ fattr ).each{|dst| alias_method dst, 'fattrs'}
|
122
|
+
end
|
123
|
+
|
124
|
+
class Module
|
125
|
+
include Fattr
|
126
|
+
|
127
|
+
def Fattrs(*a, &b)
|
128
|
+
class << self
|
129
|
+
self
|
130
|
+
end.module_eval do
|
131
|
+
fattrs(*a, &b)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def Fattr(*a, &b)
|
136
|
+
class << self
|
137
|
+
self
|
138
|
+
end.module_eval do
|
139
|
+
fattr(*a, &b)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Object
|
145
|
+
def fattrs *a, &b
|
146
|
+
sc =
|
147
|
+
class << self
|
148
|
+
self
|
149
|
+
end
|
150
|
+
sc.fattrs *a, &b
|
151
|
+
end
|
152
|
+
%w( __fattrs__ __fattr__ fattr ).each{|dst| alias_method dst, 'fattrs'}
|
153
|
+
end
|