ThiagoLelis-backgroundjob 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/attributes.rb CHANGED
@@ -1,118 +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
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
@@ -1,87 +1,87 @@
1
- unless defined? Bj
2
- class Bj
3
- #
4
- # constants and associated attrs
5
- #
6
- Bj::VERSION = "1.0.4" #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
- #
35
- # bootstrap rubygems
36
- #
37
- begin
38
- require "rubygems"
39
- rescue LoadError
40
- 42
41
- end
42
- #
43
- # rubyforge/remote
44
- #
45
- require "active_record"
46
- #
47
- # rubyforge/remote or local/lib
48
- #
49
- #%w[ attributes systemu orderedhash ].each do |lib|
50
- %w[ systemu orderedhash ].each do |lib|
51
- begin
52
- require lib
53
- rescue
54
- require libdir(lib)
55
- end
56
- end
57
- #
58
- # local
59
- #
60
- load libdir("attributes.rb")
61
- load libdir("stdext.rb")
62
- load libdir("util.rb")
63
- load libdir("errors.rb")
64
- load libdir("logger.rb")
65
- load libdir("bj.rb")
66
- load libdir("joblist.rb")
67
- load libdir("table.rb")
68
- load libdir("runner.rb")
69
- load libdir("api.rb")
70
- #
71
- # an imperfect reloading hook - because neither rails' plugins nor gems provide one, sigh...
72
- #
73
- def self.reload!
74
- background = nil
75
- ::Object.module_eval do
76
- background = Bj.runner.background
77
- remove_const :Bj rescue nil
78
- remove_const :BackgroundJob rescue nil
79
- end
80
- returned = load __FILE__ rescue nil
81
- Bj.runner.background = background if background
82
- returned
83
- end
84
- end
85
-
86
- BackgroundJob = Bj
87
- end
1
+ unless defined? Bj
2
+ class Bj
3
+ #
4
+ # constants and associated attrs
5
+ #
6
+ Bj::VERSION = "1.0.4" #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
+ #
35
+ # bootstrap rubygems
36
+ #
37
+ begin
38
+ require "rubygems"
39
+ rescue LoadError
40
+ 42
41
+ end
42
+ #
43
+ # rubyforge/remote
44
+ #
45
+ require "active_record"
46
+ #
47
+ # rubyforge/remote or local/lib
48
+ #
49
+ #%w[ attributes systemu orderedhash ].each do |lib|
50
+ %w[ systemu orderedhash ].each do |lib|
51
+ begin
52
+ require lib
53
+ rescue
54
+ require libdir(lib)
55
+ end
56
+ end
57
+ #
58
+ # local
59
+ #
60
+ load libdir("attributes.rb")
61
+ load libdir("stdext.rb")
62
+ load libdir("util.rb")
63
+ load libdir("errors.rb")
64
+ load libdir("logger.rb")
65
+ load libdir("bj.rb")
66
+ load libdir("joblist.rb")
67
+ load libdir("table.rb")
68
+ load libdir("runner.rb")
69
+ load libdir("api.rb")
70
+ #
71
+ # an imperfect reloading hook - because neither rails' plugins nor gems provide one, sigh...
72
+ #
73
+ def self.reload!
74
+ background = nil
75
+ ::Object.module_eval do
76
+ background = Bj.runner.background
77
+ remove_const :Bj rescue nil
78
+ remove_const :BackgroundJob rescue nil
79
+ end
80
+ returned = load __FILE__ rescue nil
81
+ Bj.runner.background = background if background
82
+ returned
83
+ end
84
+ end
85
+
86
+ BackgroundJob = Bj
87
+ end
data/lib/bj/api.rb CHANGED
@@ -1,161 +1,161 @@
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
- chroot do
122
- before = Dir.glob "./db/migrate/*"
123
- n = Dir.glob("./db/migrate/*_bj_*").size
124
- classname = "BjMigration#{ n }"
125
- util.spawn "#{ Bj.ruby } ./script/generate migration #{ classname }", options rescue nil
126
- after = Dir.glob "./db/migrate/*"
127
- candidates = after - before
128
- case candidates.size
129
- when 0
130
- false
131
- when 1
132
- generated = candidates.first
133
- open(generated, "w"){|fd| fd.puts Bj.table.migration_code(classname)}
134
- Bj.logger.info{ "generated <#{ generated }>" }
135
- generated
136
- else
137
- raise "ambiguous migration <#{ candidates.inspect }>"
138
- end
139
- end
140
- end
141
- #
142
- # migrate a database (production|development|etc)
143
- #
144
- def migrate options = {}
145
- options.to_options!
146
- chroot do
147
- util.spawn "rake RAILS_ENV=#{ Bj.rails_env } db:migrate", options
148
- end
149
- end
150
- #
151
- # install plugin into this rails app
152
- #
153
- def plugin options = {}
154
- options.to_options!
155
- chroot do
156
- util.spawn "#{ Bj.ruby } ./script/plugin install http://codeforpeople.rubyforge.org/svn/rails/plugins/bj --force", options
157
- end
158
- end
159
- end
160
- send :extend, API
161
- end
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
+ chroot do
122
+ before = Dir.glob "./db/migrate/*"
123
+ n = Dir.glob("./db/migrate/*_bj_*").size
124
+ classname = "BjMigration#{ n }"
125
+ util.spawn "#{ Bj.ruby } ./script/generate migration #{ classname }", options rescue nil
126
+ after = Dir.glob "./db/migrate/*"
127
+ candidates = after - before
128
+ case candidates.size
129
+ when 0
130
+ false
131
+ when 1
132
+ generated = candidates.first
133
+ open(generated, "w"){|fd| fd.puts Bj.table.migration_code(classname)}
134
+ Bj.logger.info{ "generated <#{ generated }>" }
135
+ generated
136
+ else
137
+ raise "ambiguous migration <#{ candidates.inspect }>"
138
+ end
139
+ end
140
+ end
141
+ #
142
+ # migrate a database (production|development|etc)
143
+ #
144
+ def migrate options = {}
145
+ options.to_options!
146
+ chroot do
147
+ util.spawn "rake RAILS_ENV=#{ Bj.rails_env } db:migrate", options
148
+ end
149
+ end
150
+ #
151
+ # install plugin into this rails app
152
+ #
153
+ def plugin options = {}
154
+ options.to_options!
155
+ chroot do
156
+ util.spawn "#{ Bj.ruby } ./script/plugin install http://codeforpeople.rubyforge.org/svn/rails/plugins/bj --force", options
157
+ end
158
+ end
159
+ end
160
+ send :extend, API
161
+ end