bj 1.0.0 → 1.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.
Files changed (7) hide show
  1. data/HISTORY +19 -14
  2. data/README +235 -57
  3. data/bin/bj +2 -1
  4. data/gemspec.rb +3 -2
  5. data/lib/bj.rb +4 -2
  6. data/lib/bj/attributes.rb +120 -0
  7. metadata +67 -68
data/HISTORY CHANGED
@@ -1,19 +1,24 @@
1
- 0.0.5:
2
- - use full path to ruby for plugin mode
3
- - plugin correctly installs bin -->> script
4
- - plugin install uses --force
5
- - properly quote paths in windows (spaces)
6
- - swith win signal to ABRT (was INT)
7
- - background job regrestration now uses ppid to pin the subprocess to a
8
- parent
9
- - use ppid to detect parent death and exit in event loop
10
- - don't use gem dependanices in plugin as they are broken when loading from
11
- muliple gem repos
12
- - added a small amount of drb magic that allows signals to work across
13
- processes even on windows (see http://drawohara.com/post/22540307)
1
+ 1.0.1:
2
+ - fixed name collision with 'record.attributes = hash' ar mass
3
+ assignment method (thx jon guymon)
4
+ - added new sponsor: http://igicom.com/
5
+
6
+ 0.0.5:
7
+ - use full path to ruby for plugin mode
8
+ - plugin correctly installs bin -->> script
9
+ - plugin install uses --force
10
+ - properly quote paths in windows (spaces)
11
+ - switch win signal to ABRT (was INT)
12
+ - background job regrestration now uses ppid to pin the subprocess to a
13
+ parent
14
+ - use ppid to detect parent death and exit in event loop
15
+ - don't use gem dependanices in plugin as they are broken when loading from
16
+ muliple gem repos
17
+ - added a small amount of drb magic that allows signals to work across
18
+ processes even on windows (see http://drawohara.com/post/22540307)
14
19
 
15
20
  0.0.4:
16
- - basic functionality in widows
21
+ - basic functionality in windows
17
22
  - several small bug fixes
18
23
 
19
24
  0.0.3:
data/README CHANGED
@@ -2,94 +2,257 @@ NAME
2
2
  bj
3
3
 
4
4
  SYNOPSIS
5
- bj (migration_code|generate_migration|migrate|setup|run|submit|list|set|config|pid) [options]+
5
+ bj (migration_code|generate_migration|migrate|setup|plugin|run|submit|list|set|config|pid) [options]+
6
6
 
7
7
  DESCRIPTION
8
8
  ________________________________
9
9
  Overview
10
10
  --------------------------------
11
11
 
12
- Backgroundjob (Bj) is a simple to use background priority queue for rails.
13
- Although not yet tested on windows, the design of bj is such that operation
14
- should be possible on any operating system, including M$.
12
+ Backgroundjob (Bj) is a brain dead simple zero admin background priority queue
13
+ for Rails. Bj is robust, platform independent (including windows), and
14
+ supports internal or external manangement of the background runner process.
15
15
 
16
- Jobs can be submitted to the queue directly using the api or from the
17
- commandline using the 'bj' script. For example
16
+ Jobs can be submitted to the queue directly using the api or from the command
17
+ line using the ./script/bj:
18
18
 
19
- code:
20
- Bj.submit 'cat /etc/password'
19
+ api:
20
+ Bj.submit 'cat /etc/password'
21
21
 
22
- cli:
23
- bj submit cat /etc/password
22
+ command line:
23
+ bj submit cat /etc/password
24
24
 
25
- When used from inside a rails application bj arranges that another process
26
- will always be running in the background to process the jobs that you submit.
27
- By using a separate process to run jobs bj does not impact the resource
28
- utilization of your rails application at all and enables several very cool
29
- features:
25
+ Bj's priority queue lives in the database and is therefore durable - your jobs
26
+ will live across an app crash or machine reboot. The job management is
27
+ comprehensive capturing stdout, stderr, exit_status, and temporal statistics
28
+ about each job:
30
29
 
31
- 1) Bj allows you to sumbit jobs to any of your configured databases and,
32
- in each case, spawns a separate background process to run jobs from that
33
- queue
30
+ jobs = Bj.submit array_of_commands, :priority => 42
34
31
 
35
- Bj.in :production do
36
- Bj.submit 'production_job.exe'
37
- end
32
+ ...
38
33
 
39
- Bj.in :development do
40
- Bj.submit 'development_job.exe'
41
- end
34
+ jobs.each do |job|
35
+ if job.finished?
36
+ p job.stdout
37
+ p job.stderr
38
+ p job.exit_status
39
+ p job.started_at
40
+ p job.finished_at
41
+ end
42
+ end
43
+
44
+ In addition the background runner process logs all commands run and their
45
+ exit_status to a log named using the following convention:
46
+
47
+ rails_root/log/bj.#{ HOSTNAME }.#{ RAILS_ENV }.log
48
+
49
+ Bj allows you to submit jobs to multiple databases; for instance, if your
50
+ application is running in development mode you may do:
51
+
52
+ Bj.in :production do
53
+ Bj.submit 'my_job.exe'
54
+ end
55
+
56
+ Bj manages the ever growing list of jobs ran by automatically archiving them
57
+ into another table (by default jobs > 24 hrs old are archived) to prevent the
58
+ jobs table from becoming bloated and huge.
59
+
60
+ All Bj's tables are namespaced and accessible via the Bj module:
61
+
62
+ Bj.table.job.find(:all) # jobs table
63
+ Bj.table.job_archive.find(:all) # archived jobs
64
+ Bj.table.config.find(:all) # configuration and runner state
65
+
66
+ Bj always arranges for submitted jobs to run with a current working directory
67
+ of RAILS_ROOT and with the correct RAILS_ENV setting. For example, if you
68
+ submit a job in production it will have ENV['RAILS_ENV'] == 'production'.
69
+
70
+ When Bj manages the background runner it will never outlive the rails
71
+ application - it is started and stopped on demand as the rails app is started
72
+ and stopped. This is also true for ./script/console - Bj will automatically
73
+ fire off the background runner to process jobs submitted using the console.
74
+
75
+ Bj ensures that only one background process is running for your application -
76
+ firing up three mongrels or fcgi processes will result in only one background
77
+ runner being started. Note that the number of background runners does not
78
+ determine throughput - that is determined primarily by the nature of the jobs
79
+ themselves and how much work they perform per process.
42
80
 
43
- 2) Although bj ensures that a process is always running to process
44
- your jobs, you can start a proces manually. This means that any machine
45
- capable of seeing your RAILS_ROOT can run jobs for your application, allowing
46
- one to setup a cluster of machines doing the work of a single front end rails
47
- applicaiton.
48
81
 
49
82
  ________________________________
50
- Install
83
+ Architecture
51
84
  --------------------------------
85
+
86
+ If one ignores platform specific details the design of Bj is quite simple: the
87
+ main Rails application submits jobs to table, stored in the database. The act
88
+ of submitting triggers exactly one of two things to occur:
89
+
90
+ 1) a new long running background runner to be started
91
+
92
+ 2) an existing background runner to be signaled
93
+
94
+ The background runner refuses to run two copies of itself for a given
95
+ hostname/rails_env combination. For example you may only have one background
96
+ runner processing jobs on localhost in development mode.
97
+
98
+ The background runner, under normal circumstances, is managed by Bj itself -
99
+ you need do nothing to start, monitor, or stop it - it just works. However,
100
+ some people will prefer manage their own background process, see 'External
101
+ Runner' section below for more on this.
102
+
103
+ The runner simply processes each job in a highest priority oldest-in fashion,
104
+ capturing stdout, stderr, exit_status, etc. and storing the information back
105
+ into the database while logging it's actions. When there are no jobs to run
106
+ the runner goes to sleep for 42 seconds; however this sleep is interuptable,
107
+ such as when the runner is signaled that a new job has been submitted so,
108
+ under normal circumstances there will be zero lag between job submission and
109
+ job running for an empty queue.
110
+
111
+
112
+ ________________________________
113
+ External Runner / Clustering
114
+ --------------------------------
115
+
116
+ For the paranoid control freaks out there (myself included) it is quite
117
+ possible to manage and monitor the runner process manually. This can be
118
+ desirable in production setups where monitoring software may kill leaking
119
+ rails apps periodically.
120
+
121
+ Recalling that Bj will only allow one copy of itself to process jobs per
122
+ hostname/rails_env pair we can simply do something like this in cron
123
+
124
+ cmd = bj run --forever \
125
+ --rails_env=development \
126
+ --rails_root=/Users/ahoward/rails_root
127
+
128
+ */15 * * * * $cmd
129
+
130
+ this will simply attempt the start the background runner every 15 minutes if,
131
+ and only if, it's not *already* running.
132
+
133
+ In addtion to this you'll want to tell Bj not to manage the runner itself
134
+ using
135
+
136
+ Bj.config["production.no_tickle"] = true
137
+
138
+ Note that, for clusting setups, it's as simple as adding a crontab and config
139
+ entry like this for each host. Because Bj throttles background runners per
140
+ hostname this will allow one runner per hostname - making it quite simple to
141
+ cluster three nodes behind a besieged rails application.
142
+
143
+
144
+ ________________________________
145
+ Designing Jobs
146
+ --------------------------------
147
+
148
+ Bj runs it's jobs as command line applications. It ensures that all jobs run
149
+ in RAILS_ROOT so it's quite natural to apply a pattern such as
150
+
151
+ mkdir ./jobs
152
+ edit ./jobs/background_job_to_run
153
+
154
+ ...
155
+
156
+ Bj.submit "./jobs/background_job_to_run"
157
+
158
+ If you need to run you jobs under an entire rails environment you'll need to
159
+ do this:
160
+
161
+ Bj.submit "./script/runner ./jobs/background_job_to_run"
162
+
163
+ Obviously "./script/runner" loads the rails environment for you. It's worth
164
+ noting that this happens for each job and that this is by design: the reason
165
+ is that most rails applications leak memory like a sieve so, if one were to
166
+ spawn a long running process that used the application code base you'd have a
167
+ lovely doubling of memory usage on you app servers. Although loading the
168
+ rails environment for each background job requires a little time, a little
169
+ cpu, and a lot less memory. A future version of Bj will provide a way to load
170
+ the rails environment once and to process background jobs in this environment,
171
+ but anyone wanting to use this in production will be required to duct tape
172
+ their entire chest and have a team of oxen rip off the tape without screaming
173
+ to prove steelyness of spirit and profound understanding of the other side.
174
+
175
+ Don't forget that you can submit jobs with command line arguments:
176
+
177
+ Bj.submit "./jobs/a.rb 1 foobar --force"
178
+
179
+ and that you can do powerful things by passing stdin to a job that powers
180
+ through a list of work. For instance, assume a "./jobs/bulkmail" job
181
+ resembling
182
+
183
+ STDIN.each do |line|
184
+ address = line.strip
185
+ mail_message_to address
186
+ end
52
187
 
53
- Bj can be installed two ways: as a gem or as a plugin.
188
+ then you could
54
189
 
55
- gem:
190
+ stdin = [
191
+ "foo@bar.com",
192
+ "bar@foo.com",
193
+ "ara.t.howard@codeforpeople.com",
194
+ ]
56
195
 
57
- 1) $sudo gem install bj
58
- 2) bj setup ./rails_root/
196
+ Bj.submit "./script/runner ./jobs/bulkmail", :stdin => stdin
197
+
198
+ and all those emails would be sent in the background.
199
+
200
+ Bj's power is putting jobs in the background in a simple and robust fashion.
201
+ It's your task to build intelligent jobs that leverage batch processing, and
202
+ other, possibilities. The upshot of building tasks this way is that they are
203
+ quite easy to test before submitting them from inside your application.
59
204
 
60
- plugin:
61
205
 
206
+ ________________________________
207
+ Install
208
+ --------------------------------
209
+
210
+ Bj can be installed two ways: as a plugin or via rubygems
211
+
212
+ plugin:
62
213
  1) ./script/plugin install http://codeforpeople.rubyforge.org/svn/rails/plugins/bj
63
214
  2) ./script/bj setup
64
215
 
216
+ gem:
217
+ 1) $sudo gem install bj
218
+ 2) add "require 'bj'" to config/environment.rb
219
+ 3) bj setup
220
+
65
221
  ________________________________
66
222
  Api
67
223
  --------------------------------
68
224
 
69
- submit jobs for background processing. 'jobs' can be a string or array of
70
- strings. options are applied to each job in the 'jobs', and the list of
71
- submitted jobs is always returned. options (string or symbol) can be
72
-
73
- :rails_env => production|development|key_in_database_yml
74
- when given this keyword causes bj to submit jobs to the
75
- specified database. default is RAILS_ENV.
76
-
77
- :priority => any number, including negative ones. default is zero.
78
-
79
- :tag => a tag added to the job. simply makes searching easier.
225
+ submit jobs for background processing. 'jobs' can be a string or array of
226
+ strings. options are applied to each job in the 'jobs', and the list of
227
+ submitted jobs is always returned. options (string or symbol) can be
80
228
 
81
- :env => a hash specifying any additional environment vars the background
82
- process should have.
83
-
84
- :stdin => any stdin the background process should have.
85
-
86
- eg:
87
-
88
- jobs = Bj.submit 'echo foobar', :tag => 'simple job'
89
-
90
- jobs = Bj.submit '/bin/cat', :stdin => 'in the hat'
229
+ :rails_env => production|development|key_in_database_yml
230
+ when given this keyword causes bj to submit jobs to the
231
+ specified database. default is RAILS_ENV.
232
+
233
+ :priority => any number, including negative ones. default is zero.
234
+
235
+ :tag => a tag added to the job. simply makes searching easier.
236
+
237
+ :env => a hash specifying any additional environment vars the background
238
+ process should have.
239
+
240
+ :stdin => any stdin the background process should have. must respond_to
241
+ to_s
91
242
 
92
- jobs = Bj.submit './script/runner ./scripts/a.rb', :rails_env => 'production'
243
+ eg:
244
+
245
+ jobs = Bj.submit 'echo foobar', :tag => 'simple job'
246
+
247
+ jobs = Bj.submit '/bin/cat', :stdin => 'in the hat', :priority => 42
248
+
249
+ jobs = Bj.submit './script/runner ./scripts/a.rb', :rails_env => 'production'
250
+
251
+ jobs = Bj.submit './script/runner /dev/stdin',
252
+ :stdin => 'p RAILS_ENV',
253
+ :tag => 'dynamic ruby code'
254
+
255
+ jobs Bj.submit array_of_commands, :priority => 451
93
256
 
94
257
  when jobs are run, they are run in RAILS_ROOT. various attributes are
95
258
  available *only* once the job has finished. you can check whether or not a
@@ -110,6 +273,21 @@ DESCRIPTION
110
273
  end
111
274
 
112
275
  See lib/bj/api.rb for more details.
276
+
277
+ ________________________________
278
+ Sponsors
279
+ --------------------------------
280
+ http://quintess.com/
281
+ http://www.engineyard.com/
282
+ http://igicom.com/
283
+ http://eparklabs.com/
284
+
285
+ http://your_company.com/ <<-- (targeted marketing aimed at *you*)
286
+
287
+ ________________________________
288
+ Version
289
+ --------------------------------
290
+ 1.0.1
113
291
 
114
292
  PARAMETERS
115
293
  --rails_root=rails_root, -R (0 ~> rails_root=)
data/bin/bj CHANGED
@@ -277,8 +277,9 @@ Main {
277
277
  ________________________________
278
278
  Sponsors
279
279
  --------------------------------
280
- http://www.engineyard.com/
281
280
  http://quintess.com/
281
+ http://www.engineyard.com/
282
+ http://igicom.com/
282
283
  http://eparklabs.com/
283
284
 
284
285
  http://your_company.com/ <<-- (targeted marketing aimed at *you*)
data/gemspec.rb CHANGED
@@ -12,11 +12,11 @@ Gem::Specification::new do |spec|
12
12
  spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
13
13
 
14
14
  spec.require_path = "lib"
15
- spec.autorequire = lib
15
+ #spec.autorequire = lib
16
16
 
17
17
  spec.has_rdoc = File::exist? "doc"
18
18
  spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
19
- spec.add_dependency 'attributes', '>= 5.0.0'
19
+ #spec.add_dependency 'attributes', '>= 5.0.0'
20
20
  spec.add_dependency 'main', '>= 2.6.0'
21
21
  spec.add_dependency 'systemu', '>= 1.2.0'
22
22
  spec.add_dependency 'orderedhash', '>= 0.0.3'
@@ -26,4 +26,5 @@ Gem::Specification::new do |spec|
26
26
  spec.author = "Ara T. Howard"
27
27
  spec.email = "ara.t.howard@gmail.com"
28
28
  spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
29
+ spec.rubyforge_project = "codeforpeople"
29
30
  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.0" #unless defined? Bj::VERSION
6
+ Bj::VERSION = "1.0.1" #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
@@ -46,7 +46,8 @@ unless defined? Bj
46
46
  #
47
47
  # rubyforge/remote or local/lib
48
48
  #
49
- %w[ attributes systemu orderedhash ].each do |lib|
49
+ #%w[ attributes systemu orderedhash ].each do |lib|
50
+ %w[ systemu orderedhash ].each do |lib|
50
51
  begin
51
52
  require lib
52
53
  rescue
@@ -56,6 +57,7 @@ unless defined? Bj
56
57
  #
57
58
  # local
58
59
  #
60
+ load libdir("attributes.rb")
59
61
  load libdir("stdext.rb")
60
62
  load libdir("util.rb")
61
63
  load libdir("errors.rb")
@@ -0,0 +1,120 @@
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
+ =begin
106
+ class Object
107
+ def attributes *a, &b
108
+ sc =
109
+ class << self
110
+ self
111
+ end
112
+ sc.attributes *a, &b
113
+ end
114
+ %w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
115
+ end
116
+ =end
117
+
118
+ class Module
119
+ include Attributes
120
+ end
metadata CHANGED
@@ -1,80 +1,21 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.4
3
- specification_version: 1
4
2
  name: bj
5
3
  version: !ruby/object:Gem::Version
6
- version: 1.0.0
7
- date: 2007-12-28 00:00:00 -07:00
8
- summary: bj
9
- require_paths:
10
- - lib
11
- email: ara.t.howard@gmail.com
12
- homepage: http://codeforpeople.com/lib/ruby/bj/
13
- rubyforge_project:
14
- description:
15
- autorequire: bj
16
- default_executable:
17
- bindir: bin
18
- has_rdoc: false
19
- required_ruby_version: !ruby/object:Gem::Version::Requirement
20
- requirements:
21
- - - ">"
22
- - !ruby/object:Gem::Version
23
- version: 0.0.0
24
- version:
4
+ version: 1.0.1
25
5
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message:
29
6
  authors:
30
7
  - Ara T. Howard
31
- files:
32
- - bin
33
- - bin/bj
34
- - gemspec.rb
35
- - HISTORY
36
- - install.rb
37
- - lib
38
- - lib/bj
39
- - lib/bj/api.rb
40
- - lib/bj/bj.rb
41
- - lib/bj/errors.rb
42
- - lib/bj/joblist.rb
43
- - lib/bj/logger.rb
44
- - lib/bj/runner.rb
45
- - lib/bj/stdext.rb
46
- - lib/bj/table.rb
47
- - lib/bj/util.rb
48
- - lib/bj.rb
49
- - rakefile
50
- - README
51
- - TODO
52
- test_files: []
53
-
54
- rdoc_options: []
55
-
56
- extra_rdoc_files: []
57
-
58
- executables:
59
- - bj
60
- extensions: []
61
-
62
- requirements: []
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
63
11
 
12
+ date: 2008-01-08 00:00:00 -07:00
13
+ default_executable:
64
14
  dependencies:
65
- - !ruby/object:Gem::Dependency
66
- name: attributes
67
- version_requirement:
68
- version_requirements: !ruby/object:Gem::Version::Requirement
69
- requirements:
70
- - - ">="
71
- - !ruby/object:Gem::Version
72
- version: 5.0.0
73
- version:
74
15
  - !ruby/object:Gem::Dependency
75
16
  name: main
76
17
  version_requirement:
77
- version_requirements: !ruby/object:Gem::Version::Requirement
18
+ version_requirements: !ruby/object:Gem::Requirement
78
19
  requirements:
79
20
  - - ">="
80
21
  - !ruby/object:Gem::Version
@@ -83,7 +24,7 @@ dependencies:
83
24
  - !ruby/object:Gem::Dependency
84
25
  name: systemu
85
26
  version_requirement:
86
- version_requirements: !ruby/object:Gem::Version::Requirement
27
+ version_requirements: !ruby/object:Gem::Requirement
87
28
  requirements:
88
29
  - - ">="
89
30
  - !ruby/object:Gem::Version
@@ -92,9 +33,67 @@ dependencies:
92
33
  - !ruby/object:Gem::Dependency
93
34
  name: orderedhash
94
35
  version_requirement:
95
- version_requirements: !ruby/object:Gem::Version::Requirement
36
+ version_requirements: !ruby/object:Gem::Requirement
96
37
  requirements:
97
38
  - - ">="
98
39
  - !ruby/object:Gem::Version
99
40
  version: 0.0.3
100
41
  version:
42
+ description:
43
+ email: ara.t.howard@gmail.com
44
+ executables:
45
+ - bj
46
+ extensions: []
47
+
48
+ extra_rdoc_files: []
49
+
50
+ files:
51
+ - bin
52
+ - bin/bj
53
+ - gemspec.rb
54
+ - HISTORY
55
+ - install.rb
56
+ - lib
57
+ - lib/bj
58
+ - lib/bj/api.rb
59
+ - lib/bj/attributes.rb
60
+ - lib/bj/bj.rb
61
+ - lib/bj/errors.rb
62
+ - lib/bj/joblist.rb
63
+ - lib/bj/logger.rb
64
+ - lib/bj/runner.rb
65
+ - lib/bj/stdext.rb
66
+ - lib/bj/table.rb
67
+ - lib/bj/util.rb
68
+ - lib/bj.rb
69
+ - rakefile
70
+ - README
71
+ - TODO
72
+ has_rdoc: false
73
+ homepage: http://codeforpeople.com/lib/ruby/bj/
74
+ post_install_message:
75
+ rdoc_options: []
76
+
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: "0"
90
+ version:
91
+ requirements: []
92
+
93
+ rubyforge_project: codeforpeople
94
+ rubygems_version: 1.0.1
95
+ signing_key:
96
+ specification_version: 2
97
+ summary: bj
98
+ test_files: []
99
+