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/HISTORY
CHANGED
@@ -1,64 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
- added new sponsor: http://igicom.com/
|
1
|
+
2009-01-30:
|
2
|
+
- fixed find(:first, :lock => true) issue with oracle databases
|
3
|
+
- converted clob (:text) columns to varchar (:string) when creating Bj tables (a bug in the oracle-adapter prevented the clobs from saving properly)
|
5
4
|
|
6
|
-
|
7
|
-
|
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)
|
19
|
-
|
20
|
-
0.0.4:
|
21
|
-
- basic functionality in windows
|
22
|
-
- several small bug fixes
|
5
|
+
2008-09-12:
|
6
|
+
- brought the plugin up to 1.0.4 with the new utc option (Brandon Arbini)
|
23
7
|
|
24
|
-
|
25
|
-
-
|
26
|
-
|
27
|
-
- plugin install should now pick up dependancies from plugin dir, last
|
28
|
-
release had LOAD_PATH/gem issues and was picking up globally installed
|
29
|
-
gems
|
30
|
-
|
31
|
-
- automatic management of the background processing can be turned off if you
|
32
|
-
want to manage your own processes
|
33
|
-
|
34
|
-
- all jobs are automatically restartable unless submitted with
|
35
|
-
|
36
|
-
:restartable => false
|
37
|
-
|
38
|
-
this means that, should a runner ever die, upon restart any jobs that were
|
39
|
-
mid-process will automatically be restarted
|
40
|
-
|
41
|
-
- signal based parent lifeline move out of thread and into even loop
|
42
|
-
|
43
|
-
- :lock => true added to a few AR finds to support true write serializable
|
44
|
-
transaction isolation when the db supports it
|
45
|
-
|
46
|
-
- all migrations now use :force => true and
|
47
|
-
|
48
|
-
- running 'bj setup' will always generate a new migration, even if you've
|
49
|
-
already run it before. this allows easy version upgrades.
|
50
|
-
|
51
|
-
- a few command would blow up on windows because they weren't prefixed with
|
52
|
-
'ruby'. gotta love the lack of #shebang line on windoze...
|
53
|
-
|
54
|
-
- ./script/bj is searched first before system path env var
|
55
|
-
|
56
|
-
- a default PATH is provided for whacky systems without one
|
57
|
-
|
58
|
-
- database.yml is filtered through ERB ala rails
|
59
|
-
|
60
|
-
0.0.2:
|
61
|
-
- path bug fixes
|
62
|
-
|
63
|
-
0.0.1:
|
64
|
-
- initial release
|
8
|
+
2007-12-18T14:19:22.86-07:00
|
9
|
+
- corrected install libs
|
data/README
CHANGED
@@ -1,258 +1,100 @@
|
|
1
1
|
NAME
|
2
|
-
|
2
|
+
bj
|
3
3
|
|
4
4
|
SYNOPSIS
|
5
|
-
|
5
|
+
bj (migration_code|generate_migration|migrate|setup|run|submit|list|set|config|pid) [options]+
|
6
6
|
|
7
7
|
DESCRIPTION
|
8
8
|
________________________________
|
9
9
|
Overview
|
10
10
|
--------------------------------
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
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$.
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
Jobs can be submitted to the queue directly using the api or from the
|
17
|
+
commandline using the 'bj' script. For example
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
code:
|
20
|
+
Bj.submit 'cat /etc/password'
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
cli:
|
23
|
+
bj submit cat /etc/password
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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:
|
29
30
|
|
30
|
-
|
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
|
31
34
|
|
32
|
-
|
33
|
-
|
34
|
-
|
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.
|
80
|
-
|
81
|
-
|
82
|
-
________________________________
|
83
|
-
Architecture
|
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
|
187
|
-
|
188
|
-
then you could
|
189
|
-
|
190
|
-
stdin = [
|
191
|
-
"foo@bar.com",
|
192
|
-
"bar@foo.com",
|
193
|
-
"ara.t.howard@codeforpeople.com",
|
194
|
-
]
|
195
|
-
|
196
|
-
Bj.submit "./script/runner ./jobs/bulkmail", :stdin => stdin
|
197
|
-
|
198
|
-
and all those emails would be sent in the background.
|
35
|
+
Bj.in :production do
|
36
|
+
Bj.submit 'production_job.exe'
|
37
|
+
end
|
199
38
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
quite easy to test before submitting them from inside your application.
|
39
|
+
Bj.in :development do
|
40
|
+
Bj.submit 'development_job.exe'
|
41
|
+
end
|
204
42
|
|
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.
|
205
48
|
|
206
49
|
________________________________
|
207
50
|
Install
|
208
51
|
--------------------------------
|
209
52
|
|
210
|
-
Bj can be installed two ways: as a
|
211
|
-
|
212
|
-
plugin:
|
213
|
-
1) ./script/plugin install http://codeforpeople.rubyforge.org/svn/rails/plugins/bj
|
214
|
-
2) ./script/bj setup
|
53
|
+
Bj can be installed two ways: as a gem or as a plugin.
|
215
54
|
|
216
55
|
gem:
|
217
56
|
1) $sudo gem install bj
|
218
57
|
2) add "require 'bj'" to config/environment.rb
|
219
58
|
3) bj setup
|
220
59
|
|
60
|
+
plugin:
|
61
|
+
1) ./script/plugin install http://codeforpeople.rubyforge.org/svn/rails/plugins/bj
|
62
|
+
2) ./script/bj setup
|
63
|
+
|
221
64
|
________________________________
|
222
65
|
Api
|
223
66
|
--------------------------------
|
224
67
|
|
225
|
-
|
226
|
-
|
227
|
-
|
68
|
+
submit jobs for background processing. 'jobs' can be a string or array of
|
69
|
+
strings. options are applied to each job in the 'jobs', and the list of
|
70
|
+
submitted jobs is always returned. options (string or symbol) can be
|
228
71
|
|
229
|
-
|
230
|
-
|
231
|
-
|
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
|
72
|
+
:rails_env => production|development|key_in_database_yml
|
73
|
+
when given this keyword causes bj to submit jobs to the
|
74
|
+
specified database. default is RAILS_ENV.
|
242
75
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
76
|
+
:priority => any number, including negative ones. default is zero.
|
77
|
+
|
78
|
+
:tag => a tag added to the job. simply makes searching easier.
|
79
|
+
|
80
|
+
:env => a hash specifying any additional environment vars the background
|
81
|
+
process should have.
|
82
|
+
|
83
|
+
:stdin => any stdin the background process should have.
|
84
|
+
|
85
|
+
eg:
|
86
|
+
|
87
|
+
jobs = Bj.submit 'echo foobar', :tag => 'simple job'
|
88
|
+
|
89
|
+
jobs = Bj.submit '/bin/cat', :stdin => 'in the hat', :priority => 42
|
90
|
+
|
91
|
+
jobs = Bj.submit './script/runner ./scripts/a.rb', :rails_env => 'production'
|
92
|
+
|
93
|
+
jobs = Bj.submit './script/runner /dev/stdin',
|
94
|
+
:stdin => 'p RAILS_ENV',
|
95
|
+
:tag => 'dynamic ruby code'
|
254
96
|
|
255
|
-
|
97
|
+
jobs Bj.submit array_of_commands, :priority => 451
|
256
98
|
|
257
99
|
when jobs are run, they are run in RAILS_ROOT. various attributes are
|
258
100
|
available *only* once the job has finished. you can check whether or not a
|
@@ -277,17 +119,9 @@ DESCRIPTION
|
|
277
119
|
________________________________
|
278
120
|
Sponsors
|
279
121
|
--------------------------------
|
280
|
-
http://quintess.com/
|
281
122
|
http://www.engineyard.com/
|
282
|
-
http://
|
123
|
+
http://quintess.com/
|
283
124
|
http://eparklabs.com/
|
284
|
-
|
285
|
-
http://your_company.com/ <<-- (targeted marketing aimed at *you*)
|
286
|
-
|
287
|
-
________________________________
|
288
|
-
Version
|
289
|
-
--------------------------------
|
290
|
-
1.0.1
|
291
125
|
|
292
126
|
PARAMETERS
|
293
127
|
--rails_root=rails_root, -R (0 ~> rails_root=)
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the bj plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the bj plugin.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'Bj'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
data/background.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = %q{backgroundjob}
|
3
|
+
s.version = "1.0.4"
|
4
|
+
|
5
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
6
|
+
s.authors = ["Ara T. Howard"]
|
7
|
+
s.date = %q{2008-12-24}
|
8
|
+
s.default_executable = %q{bin/bj}
|
9
|
+
s.email = %q{ara.t.howard@gmail.com}
|
10
|
+
s.executables = ["bj"]
|
11
|
+
s.files = ["background.gemspec", "bin", "bin/bj", "HISTORY", "init.rb", "install.rb", "lib", "lib/arrayfields.rb", "lib/attributes.rb", "lib/bj", "lib/bj/api.rb", "lib/bj/attributes.rb", "lib/bj/bj.rb", "lib/bj/errors.rb", "lib/bj/joblist.rb", "lib/bj/logger.rb", "lib/bj/runner.rb", "lib/bj/stdext.rb", "lib/bj/table.rb", "lib/bj/util.rb", "lib/bj.rb", "lib/fattr.rb", "lib/main", "lib/main/base.rb", "lib/main/cast.rb", "lib/main/factories.rb", "lib/main/getoptlong.rb", "lib/main/logger.rb", "lib/main/mode.rb", "lib/main/parameter.rb", "lib/main/softspoken.rb", "lib/main/stdext.rb", "lib/main/usage.rb", "lib/main/util.rb", "lib/main.rb", "lib/orderedautohash.rb", "lib/orderedhash.rb", "lib/systemu.rb", "Rakefile", "README", "script", "script/bj", "tasks", "tasks/bj_tasks.rake", "test", "test/bj_test.rb", "uninstall.rb"]
|
12
|
+
s.has_rdoc = false
|
13
|
+
s.homepage = %q{http://codeforpeople.com/lib/ruby/bj}
|
14
|
+
s.require_paths = ["lib"]
|
15
|
+
s.rubygems_version = %q{1.3.1}
|
16
|
+
s.summary = %q{Backgroundjob (Bj) is a simple to use background priority queue for rails.}
|
17
|
+
s.rubyforge_project = ""
|
18
|
+
end
|