bj 0.0.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.
data/gemspec.rb ADDED
@@ -0,0 +1,29 @@
1
+ lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
2
+ require 'rubygems'
3
+
4
+ Gem::Specification::new do |spec|
5
+ $VERBOSE = nil
6
+ spec.name = lib
7
+ spec.version = version
8
+ spec.platform = Gem::Platform::RUBY
9
+ spec.summary = lib
10
+
11
+ spec.files = Dir::glob "**/**"
12
+ spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
13
+
14
+ spec.require_path = "lib"
15
+ spec.autorequire = lib
16
+
17
+ spec.has_rdoc = File::exist? "doc"
18
+ spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
19
+ spec.add_dependency 'attributes', '>= 5.0.0'
20
+ spec.add_dependency 'main', '>= 2.6.0'
21
+ spec.add_dependency 'systemu', '>= 1.2.0'
22
+ spec.add_dependency 'orderedhash', '>= 0.0.3'
23
+
24
+ spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
25
+
26
+ spec.author = "Ara T. Howard"
27
+ spec.email = "ara.t.howard@gmail.com"
28
+ spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
29
+ end
data/install.rb ADDED
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rbconfig'
3
+ require 'find'
4
+ require 'ftools'
5
+ require 'tempfile'
6
+ include Config
7
+
8
+ LIBDIR = "lib"
9
+ LIBDIR_MODE = 0644
10
+
11
+ BINDIR = "bin"
12
+ BINDIR_MODE = 0755
13
+
14
+
15
+ $srcdir = CONFIG["srcdir"]
16
+ $version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
17
+ $libdir = File.join(CONFIG["libdir"], "ruby", $version)
18
+ $archdir = File.join($libdir, CONFIG["arch"])
19
+ $site_libdir = $:.find {|x| x =~ /site_ruby$/}
20
+ $bindir = CONFIG["bindir"] || CONFIG['BINDIR']
21
+ $ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
22
+ $ruby_ext = CONFIG['EXEEXT'] || ''
23
+ $ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
24
+
25
+ if !$site_libdir
26
+ $site_libdir = File.join($libdir, "site_ruby")
27
+ elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
28
+ $site_libdir = File.join($site_libdir, $version)
29
+ end
30
+
31
+ def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
32
+ #{{{
33
+ path = []
34
+ dir = []
35
+ Find.find(srcdir) do |f|
36
+ next unless FileTest.file?(f)
37
+ next if (f = f[srcdir.length+1..-1]) == nil
38
+ next if (/CVS$/ =~ File.dirname(f))
39
+ next if f =~ %r/\.lnk/
40
+ path.push f
41
+ dir |= [File.dirname(f)]
42
+ end
43
+ for f in dir
44
+ next if f == "."
45
+ next if f == "CVS"
46
+ File::makedirs(File.join(destdir, f))
47
+ end
48
+ for f in path
49
+ next if (/\~$/ =~ f)
50
+ next if (/^\./ =~ File.basename(f))
51
+ unless bin
52
+ File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
53
+ else
54
+ from = File.join(srcdir, f)
55
+ to = File.join(destdir, f)
56
+ shebangify(from) do |sf|
57
+ $deferr.print from, " -> ", File::catname(from, to), "\n"
58
+ $deferr.printf "chmod %04o %s\n", mode, to
59
+ File::install(sf, to, mode, false)
60
+ end
61
+ end
62
+ end
63
+ #}}}
64
+ end
65
+ def shebangify f
66
+ #{{{
67
+ open(f) do |fd|
68
+ buf = fd.read 42
69
+ if buf =~ %r/^\s*#\s*!.*ruby/o
70
+ ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
71
+ begin
72
+ fd.rewind
73
+ ftmp.puts "#!#{ $ruby }"
74
+ while((buf = fd.read(8192)))
75
+ ftmp.write buf
76
+ end
77
+ ftmp.close
78
+ yield ftmp.path
79
+ ensure
80
+ ftmp.close!
81
+ end
82
+ else
83
+ yield f
84
+ end
85
+ end
86
+ #}}}
87
+ end
88
+ def ARGV.switch
89
+ #{{{
90
+ return nil if self.empty?
91
+ arg = self.shift
92
+ return nil if arg == '--'
93
+ if arg =~ /^-(.)(.*)/
94
+ return arg if $1 == '-'
95
+ raise 'unknown switch "-"' if $2.index('-')
96
+ self.unshift "-#{$2}" if $2.size > 0
97
+ "-#{$1}"
98
+ else
99
+ self.unshift arg
100
+ nil
101
+ end
102
+ #}}}
103
+ end
104
+ def ARGV.req_arg
105
+ #{{{
106
+ self.shift || raise('missing argument')
107
+ #}}}
108
+ end
109
+ def linkify d, linked = []
110
+ #--{{{
111
+ if test ?d, d
112
+ versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
113
+ versioned.each do |v|
114
+ src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
115
+ lnk = nil
116
+ begin
117
+ if test ?l, dst
118
+ lnk = "#{ dst }.lnk"
119
+ puts "#{ dst } -> #{ lnk }"
120
+ File::rename dst, lnk
121
+ end
122
+ unless test ?e, dst
123
+ puts "#{ src } -> #{ dst }"
124
+ File::copy src, dst
125
+ linked << dst
126
+ end
127
+ ensure
128
+ if lnk
129
+ at_exit do
130
+ puts "#{ lnk } -> #{ dst }"
131
+ File::rename lnk, dst
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ linked
138
+ #--}}}
139
+ end
140
+
141
+
142
+ #
143
+ # main program
144
+ #
145
+
146
+ libdir = $site_libdir
147
+ bindir = $bindir
148
+ no_linkify = false
149
+ linked = nil
150
+ help = false
151
+
152
+ usage = <<-usage
153
+ #{ File::basename $0 }
154
+ -d, --destdir <destdir>
155
+ -l, --libdir <libdir>
156
+ -b, --bindir <bindir>
157
+ -r, --ruby <ruby>
158
+ -n, --no_linkify
159
+ -s, --sudo
160
+ -h, --help
161
+ usage
162
+
163
+ begin
164
+ while switch = ARGV.switch
165
+ case switch
166
+ when '-d', '--destdir'
167
+ libdir = ARGV.req_arg
168
+ when '-l', '--libdir'
169
+ libdir = ARGV.req_arg
170
+ when '-b', '--bindir'
171
+ bindir = ARGV.req_arg
172
+ when '-r', '--ruby'
173
+ $ruby = ARGV.req_arg
174
+ when '-n', '--no_linkify'
175
+ no_linkify = true
176
+ when '-s', '--sudo'
177
+ sudo = 'sudo'
178
+ when '-h', '--help'
179
+ help = true
180
+ else
181
+ raise "unknown switch #{switch.dump}"
182
+ end
183
+ end
184
+ rescue
185
+ STDERR.puts $!.to_s
186
+ STDERR.puts usage
187
+ exit 1
188
+ end
189
+
190
+ if help
191
+ STDOUT.puts usage
192
+ exit
193
+ end
194
+
195
+ system "#{ sudo } #{ $ruby } pre-install.rb" if test(?s, 'pre-install.rb')
196
+
197
+ unless no_linkify
198
+ linked = linkify('lib') + linkify('bin')
199
+ end
200
+
201
+ system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
202
+
203
+ install_rb(LIBDIR, libdir, LIBDIR_MODE)
204
+ install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
205
+
206
+ if linked
207
+ linked.each{|path| File::rm_f path}
208
+ end
209
+
210
+ system "#{ sudo } #{ $ruby } post-install.rb" if test(?s, 'post-install.rb')
data/lib/bj.rb ADDED
@@ -0,0 +1,79 @@
1
+ unless defined? Bj
2
+ class Bj
3
+ #
4
+ # constants and associated attrs
5
+ #
6
+ Bj::VERSION = "0.0.1" unless
7
+ defined? Bj::VERSION
8
+ def self.version() Bj::VERSION end
9
+
10
+ Bj::LIBDIR = File.expand_path(File::join(File.dirname(__FILE__), "bj")) + File::SEPARATOR unless
11
+ defined? Bj::LIBDIR
12
+ def self.libdir(*value)
13
+ unless value.empty?
14
+ File.join libdir, *value
15
+ else
16
+ Bj::LIBDIR
17
+ end
18
+ end
19
+
20
+ module EXIT
21
+ SUCCESS = 0
22
+ FAILURE = 1
23
+ WARNING = 42
24
+ end
25
+ #
26
+ # built-in
27
+ #
28
+ require "socket"
29
+ require "yaml"
30
+ require "thread"
31
+ require "rbconfig"
32
+ #
33
+ # bootstrap rubygems
34
+ #
35
+ begin
36
+ require "rubygems"
37
+ rescue LoadError
38
+ 42
39
+ end
40
+ #
41
+ # rubyforge/remote
42
+ #
43
+ require "active_record"
44
+ #
45
+ # rubyforge/remote or local/lib
46
+ #
47
+ %w[ attributes main systemu orderedhash ].each do |lib|
48
+ begin
49
+ require lib
50
+ rescue
51
+ require libdir(lib)
52
+ end
53
+ end
54
+ #
55
+ # local
56
+ #
57
+ load libdir("stdext.rb")
58
+ load libdir("util.rb")
59
+ load libdir("errors.rb")
60
+ load libdir("logger.rb")
61
+ load libdir("bj.rb")
62
+ load libdir("joblist.rb")
63
+ load libdir("table.rb")
64
+ load libdir("runner.rb")
65
+ load libdir("api.rb")
66
+ #
67
+ # an imperfect reloading hook - because neither rails' plugins nor gems provide one, sigh...
68
+ #
69
+ def self.reload!
70
+ ::Object.module_eval do
71
+ remove_const :Bj rescue nil
72
+ remove_const :BackgroundJob rescue nil
73
+ end
74
+ load __FILE__ rescue nil
75
+ end
76
+ end
77
+
78
+ BackgroundJob = Bj
79
+ end
data/lib/bj/api.rb ADDED
@@ -0,0 +1,144 @@
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'
34
+ #
35
+ # jobs = Bj.submit './script/runner ./scripts/a.rb', :rails_env => 'production'
36
+ #
37
+ # when jobs are run, they are run in RAILS_ROOT. various attributes are
38
+ # available *only* once the job has finished. you can check whether or not
39
+ # a job is finished by using the #finished method, which simple does a
40
+ # reload and checks to see if the exit_status is non-nil.
41
+ #
42
+ # eg:
43
+ #
44
+ # jobs = Bj.submit list_of_jobs, :tag => 'important'
45
+ # ...
46
+ #
47
+ # jobs.each do |job|
48
+ # if job.finished?
49
+ # p job.exit_status
50
+ # p job.stdout
51
+ # p job.stderr
52
+ # end
53
+ # end
54
+ #
55
+ #
56
+ def submit jobs, options = {}, &block
57
+ options.to_options!
58
+ Bj.transaction(options) do
59
+ table.job.submit jobs, options, &block
60
+ end
61
+ ensure
62
+ Bj.runner.tickle unless options[:no_tickle]
63
+ end
64
+ #
65
+ # this method changes the context under which bj is operating. a context is
66
+ # a RAILS_ENV. the method accepts a block and it used to alter the
67
+ # behaviour of the bj lib on a global scale such that all operations,
68
+ # spawning of background runnner processes, etc, occur in that context.
69
+ #
70
+ # eg:
71
+ #
72
+ # Bj.in :production do
73
+ # Bj.submit './script/runner ./scripts/facebook_notification.rb'
74
+ # end
75
+ #
76
+ # Bj.in :development do
77
+ # Bj.submit 'does_this_eat_memory.exe'
78
+ # end
79
+ #
80
+ def in rails_env = Bj.rails_env, &block
81
+ transaction(:rails_env => rails_env.to_s, &block)
82
+ end
83
+ #
84
+ # list simply returns a list of all jobs in the job table
85
+ #
86
+ def list options = {}, &block
87
+ Bj.transaction(options) do
88
+ table.job.find(:all, options)
89
+ end
90
+ end
91
+ #
92
+ #
93
+ #
94
+ def run options = {}
95
+ runner.run options
96
+ end
97
+ #
98
+ # generate a migration and migrate a database (production/development/etc)
99
+ #
100
+ def setup options = {}
101
+ options.to_options!
102
+ chroot do
103
+ generate_migration options
104
+ migrate options
105
+ end
106
+ end
107
+ #
108
+ # generate_migration, suprisingly, generates the single migration needed for
109
+ # bj. you'll notice the the migration is very short as the migration
110
+ # classes themselves are inner classes of the respective bj table class.
111
+ # see lib/bj/table.rb for details.
112
+ #
113
+ def generate_migration options = {}
114
+ options.to_options!
115
+ chroot do
116
+ before = Dir.glob "./db/migrate/*"
117
+ util.spawn "./script/generate migration BjMigration", options rescue nil
118
+ after = Dir.glob "./db/migrate/*"
119
+ candidates = after - before
120
+ case candidates.size
121
+ when 0
122
+ false
123
+ when 1
124
+ generated = candidates.first
125
+ open(generated, "w"){|fd| fd.puts Bj.table.migration_code}
126
+ Bj.logger.info{ "generated <#{ generated }>" }
127
+ generated
128
+ else
129
+ raise "ambiguous migration <#{ candidates.inspect }>"
130
+ end
131
+ end
132
+ end
133
+ #
134
+ # migrate a database (production|development|etc)
135
+ #
136
+ def migrate options = {}
137
+ options.to_options!
138
+ chroot do
139
+ util.spawn "rake RAILS_ENV=#{ Bj.rails_env } db:migrate", options
140
+ end
141
+ end
142
+ end
143
+ send :extend, API
144
+ end