rfdonnelly / jobrnr Goto Github PK
View Code? Open in Web Editor NEWJobrnr runs jobs.
License: Apache License 2.0
Jobrnr runs jobs.
License: Apache License 2.0
Multi-line descriptions are not indented properly. Only first line is indented.
Example:
Jobrnr::PlusOptionParser.parse({description: "a\nb", options: {}}, '+help')
DESCRIPTION
a
b
options = parse_plus_options(plus_options) do
name "command"
synopsis "command [options]"
description <<-EOF
Multi-line
description
EOF
option :option1 do
description "This is the first option."
default "default-value"
end
option :option_two do
description "This is option two."
default 5
end
extra <<-EOF
Multi-line
extra
EOF
end
lib/jobrnr/dsl/job_builder.rb:26:in `repeat': uninitialized constant Jobrnr::TypeError (NameError)
Did you mean? TypeError
diff --git a/lib/jobrnr/dsl/job_builder.rb b/lib/jobrnr/dsl/job_builder.rb
index 66f392c..acd306c 100644
--- a/lib/jobrnr/dsl/job_builder.rb
+++ b/lib/jobrnr/dsl/job_builder.rb
@@ -23,7 +23,7 @@ module Jobrnr
def repeat(times)
if !times.is_a?(Integer) || times < 0
- raise Jobrnr::TypeError, "'repeat' expects a positive Integer" \
+ raise Jobrnr::ArgumentError, "'repeat' expects a positive Integer" \
" but was given value of '#{times}' of type" \
" '#{times.class.name}' @ #{source}"
end
In general, catch bad usage and provide good error messages. Some work has already been done to validate DSL methods' inputs. This issue is an attempt to identify all areas where we can check, catch, and report bad usage.
job
command
job.execute
command
job.repeat
command
import
command
For method type checking.
When outputting option help, +help should be auto added to the help text.
--seed
optionAdd features to allow job descriptions to produce man page like output.
Jobrnr can already produce the OPTIONS section.
SYNOPSIS
jobrnr index.jr
DESCRIPTION
My job description.
OPTIONS
+bool-option[=<value>]
This is a Boolean option. Default: false
+iter=<value>
Number of iterations Default: 2
+test=<value>
Name of test to run. Default: 'default'
EXAMPLES
Run all basic regression.
jobrnr file.jr
Run more iterations.
jobrnr file.jr +iter=50
#!/usr/bin/env jobrnr
job :test do
execute 'echo'
repeat 0
end
Terminates w/o running any jobs.
Loops endlessly with:
Running:0 Queued:0 Completed:0 Passed:0 Failed:0
Running:0 Queued:0 Completed:0 Passed:0 Failed:0
Running:0 Queued:0 Completed:0 Passed:0 Failed:0
Running:0 Queued:0 Completed:0 Passed:0 Failed:0
Running:0 Queued:0 Completed:0 Passed:0 Failed:0
jobrnr/lib/jobrnr/plus_option_parser.rb:243: warning: constant ::Fixnum is deprecated
jobrnr/lib/jobrnr/script.rb:24:in `read': No such file or directory @ rb_sysopen - non-existent-file.jr (Errno::ENOENT)
jobrnr non-existent-file.jr
Repeat jobs head of line block the job queue until all iterations have been scheduled. See
jobrnr/lib/jobrnr/job/dispatch.rb
Line 117 in c968b4a
Instead, repeat jobs should be sent to the back of the queue after scheduling repeat job iteration. This will give other jobs a change to schedule.
JobRnr always exits with zero status even when failures present.
Rename to better differentiate between job description options vs jobrnr application options.
Before:
options.output_directory = "..."
After:
jobrnr.output_directory = "..."
+boolean-option => options[:boolean_option] = true
+no-boolean-option => options[:boolean_option] = false
Example:
jobrnr --opt0 dot-jr.jr --opt1 --dot-jr-opt0 --dot-jr-opt1
Call API defined method in dot-jr.jr to add options to OptionParser
. How does this work with import?
Pro: dot-jr options show in --help
.
Con: Not obvious from looking at command line what is a jobrnr option and a dot-jr option.
Example using --opts
option:
jobrnr --opt0 dot-jr.jr --opt1 --opts '--dot-jr-opt0 --dot-jr-opt1'
Con: Additional typing overhead.
Con: Need for quotes.
Example using +
as prefix:
jobrnr --opt0 dot-jr.jr --opt1 ++dot-jr-opt0 ++dot-jr-opt1
The seed substitution isn't documented anywhere. Add doc to --help-format
.
JobRnr currently terminates when all jobs have completed regardless of success. Add option to terminate after seeing some number of failures.
Add ability to import
all jobs from a job description file.
import 'prefix', :all, 'file.jr'
So we can give more information to the user and differentiate between a jobrnr error and other errors.
jobrnr <options-before-dot-jr> dot-jr.jr
jobrnr dot-jr.jr <options-after-dot-jr>
--max-jobs
default is 1
dot-jr.jr:
options.max_jobs = 4
command line:
JOBRNR_MAX_JOBS=2 jobrnr --max-jobs 3 dot-jr.jr --max-jobs 5
Initial value for the --max-jobs option is 1 (default). It gets overridden by environment variable to 2. The overridden by --max-jobs option on command line to 3. Then overriden by dot-jr.jr to 4. Finally overridden to 5 by another --max-jobs option on the command line.
Would be useful to to have a per job timeout feature to fail the job if it takes longer than expected.
'plugin' sounds old
Job description files should support relative paths to simplify specification of paths.
snippet from current examples/import/index.js
import 'child', [:compile, :run_random], File.join(File.dirname(__FILE__), "child.jr")
options.directory = File.join(File.dirname(__FILE__), "output")
snippet from desired examples/import/index.js
import 'child', [:compile, :run_random], "child.jr"
options.directory = "output"
Add queues to help with resource (e.g. licenses) management. There would be both a per queue job limit and the pre-existing global job limit --max-jobs
.
Example queue configuration:
diff --git a/lib/jobrnr/graph.rb b/lib/jobrnr/graph.rb
index 7bf9f83..afb9da8 100644
--- a/lib/jobrnr/graph.rb
+++ b/lib/jobrnr/graph.rb
@@ -42,6 +42,8 @@ module Jobrnr
lines << "#{j.id} -> #{s.id}"
end
end
+
+ lines << '%s -> %s [ label = "%d" ]' % [j.id, j.id, j.iterations] if j.iterations > 1
end
[
post_interval
event.pre_parse
eventpost_parse
eventOptionParser
instanceTo print the commands that will be run without actually running them.
Same stats print multiple times. Stats should print only when they change.
Apply patch:
diff --git a/examples/repeat/index.jr b/examples/repeat/index.jr
index aedbaf1..f8a8395 100644
--- a/examples/repeat/index.jr
+++ b/examples/repeat/index.jr
@@ -1,5 +1,5 @@
job :repeat do
- execute 'sleep #{rand(5)}'
+ execute 'sleep #{4 + rand(5)}'
repeat 50
end
Run:
jr examples/repeat/index.jr
jobrnr: DEBUG: digraph DependencyGraph {
repeat;
}
Running: 'sleep 6' regr00 iter0
Running: 'sleep 7' regr01 iter1
Running: 'sleep 7' regr02 iter2
Running: 'sleep 6' regr03 iter3
Running: 'sleep 6' regr04 iter4
Running:5 Queued:45 Completed:0 Passed:0 Failed:0
Running:5 Queued:45 Completed:0 Passed:0 Failed:0
Running:5 Queued:45 Completed:0 Passed:0 Failed:0
Running:5 Queued:45 Completed:0 Passed:0 Failed:0
Running:5 Queued:45 Completed:0 Passed:0 Failed:0
Running:5 Queued:45 Completed:0 Passed:0 Failed:0
...
When the max failures limit is reached, it is unclear why jobrnr terminates early. Add a notification for termination reason.
Plugins need more information. For example, the jobrnr output directory.
When --max-failures
is reached, JobRnr exists immediately. Instead, it should stop submitting new jobs and let and running jobs finish.
There is no way to specify a hexadecimal seed without the '0x' prefix. Remove '0x' prefix from format and require job descriptions make the prefix explicit.
The current behavior is to recycle job logs on job success (passing job logs get overwritten).
Add --save-all
option to save all job logs. This option should qualify the last term (!job_instance.success?
) of https://github.com/rfdonnelly/jobrnr/blob/master/lib/jobrnr/job/dispatch.rb#L78.
Importing a job description file with the same basename as the current job description file results in defining different classes with the same name.
job_rnr/lib/job_rnr/script.rb:11: warning: already initialized constant Regression
job_rnr/lib/job_rnr/script.rb:11: warning: previous definition of Regression was here
See call to classify
.
scripts/stow/job_rnr/lib/job_rnr/script.rb
18- def from_file(filename, base_class = nil)
19- basename = File.basename(filename, '.jr')
20: classname = classify(basename)
21-
22- code_string = IO.read(filename)
23- from_string(classname, code_string, filename, base_class)
24- end
Boolean plus option help format is incorrect.
OPTIONS
+default-false[=<value>]
Default: false
+default-true[=<value>]
Default: true
OPTIONS
+default-false=<value>
Default: false
+default-true
Default: true
Jobs should only be run if all parents pass.
Input:
job :passing_parent do
execute 'true'
end
job :failing_parent do
execute 'false'
end
job :failing_child, [:passing_parent, :failing_parent] do
execute 'ERROR: this job should not run'
end
Command:
jobrnr examples/multiple-parents/index.jr --max-failures 2
Output:
Running: 'true' jobrnr00
Running: 'false' jobrnr01
Running:2 Queued:0 Completed:0 Passed:0 Failed:0
PASSED: 'true' jobrnr00 in 0.00s
FAILED: 'false' jobrnr01 in 0.00s
Running: 'ERROR: this job should not run' jobrnr02
Running:1 Queued:0 Completed:2 Passed:1 Failed:1
FAILED: 'ERROR: this job should not run' jobrnr02 in 0.01s <===========
Running:0 Queued:0 Completed:3 Passed:1 Failed:2
jobrnr/lib/jobrnr/options.rb:59:in `parse': invalid option: --maxjobs (OptionParser::InvalidOption)
from jobrnr/lib/jobrnr/application.rb:10:in `run'
...
Importing non-existent jobs silently fails. This condition should result in an error.
command:
jr index.jr
index.jr
import 'import', [:non_existent_job], File.join(File.dirname(__FILE__), "import.jr")
import.jr
job :job do
execute 'sleep 1'
end
Needs to account for subprocesses.
Something like
Job 'absent_parent' does not exist for 'child' job @ error.jr:1
.../jobrnr/lib/jobrnr/job/definition.rb:19:in `block in initialize': undefined method `successors' for nil:NilClass (NoMethodError)
error.jr
job :child, :absent_parent do
execute 'true'
end
jobrnr error.jr
> jobrnr --bad-option rdonnell@dline06 /home/rdonnell/sbox/cvac/1
/home/rdonnell/sbox/cvac/1/common/scripts/stow/jobrnr/lib/jobrnr/log.rb:14:in `report': uninitialized class variable @@verbosity in Jobrnr::Log (NameError)
Did you mean? verbosity=
from /home/rdonnell/sbox/cvac/1/common/scripts/stow/jobrnr/lib/jobrnr/log.rb:22:in `error'
from /home/rdonnell/sbox/cvac/1/common/scripts/stow/jobrnr/lib/jobrnr/application.rb:13:in `rescue in run'
from /home/rdonnell/sbox/cvac/1/common/scripts/stow/jobrnr/lib/jobrnr/application.rb:10:in `run'
from /home/rdonnell/sbox/cvac/1/common/scripts/jobrnr:7:in `<main>'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.