mobilize-base 1.0.75 → 1.0.81

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -120,7 +120,7 @@ same one that contains your Rakefile)
120
120
  Inside the Rakefile in your project's root folder, make sure you have:
121
121
 
122
122
  ``` ruby
123
- require 'mobilize-base/rakes'
123
+ require 'mobilize-base/tasks'
124
124
  ```
125
125
 
126
126
  This defines rake tasks essential to run the environment.
@@ -489,26 +489,26 @@ name>))` and enter values under each header:
489
489
 
490
490
  * status Mobilize writes this field with the last status returned by the job
491
491
 
492
- * task1..task5 List of tasks to be performed by the job.
493
- * Tasks have this syntax: <handler>.<call> <params>.
494
- * handler specifies the file that should receive the task
492
+ * stage1..stage5 List of stages to be performed by the job.
493
+ * Stages have this syntax: <handler>.<call> <params>.
494
+ * handler specifies the file that should receive the stage
495
495
  * the call specifies the method within the file. The method should
496
- be called `"<handler>.<call>_by_task_path"`
496
+ be called `"<handler>.<call>_by_stage_path"`
497
497
  * the params the method accepts, which are custom to each
498
- task. These should be of the for `<key1>: <value1>, <key2>: <value2>`, where
498
+ stage. These should be of the for `<key1>: <value1>, <key2>: <value2>`, where
499
499
  `<key>` is an unquoted string and `<value>` is a quoted string, an
500
500
  integer, an array (delimited by square braces), or a hash (delimited by
501
501
  curly braces).
502
- * For mobilize-base, the following tasks are available:
502
+ * For mobilize-base, the following stages are available:
503
503
  * gsheet.read `source: <input_gsheet_full_path>`, which reads the sheet.
504
504
  * The gsheet_full_path should be of the form `<gbook_name>/<gsheet_name>`. The test uses
505
- "Requestor_mobilize(test)/base1_task1.in".
506
- * gsheet.write `source: <task_relative_path>`,`target: <target_gsheet_path>`,
507
- which writes the specified task output to the target_gsheet.
508
- * The task_relative_path should be of the form `<task_column>` or
509
- `<job_name/task_column>`. The test uses "base1/task1" for the first test
510
- and simply "task1" for the second test. Both of these take the output
511
- from the first task.
505
+ "Requestor_mobilize(test)/base1_stage1.in".
506
+ * gsheet.write `source: <stage_relative_path>`,`target: <target_gsheet_path>`,
507
+ which writes the specified stage output to the target_gsheet.
508
+ * The stage_relative_path should be of the form `<stage_column>` or
509
+ `<job_name/stage_column>`. The test uses "base1/stage1" for the first test
510
+ and simply "stage1" for the second test. Both of these take the output
511
+ from the first stage.
512
512
  * The test uses "Requestor_mobilize(test)/base1.out" and
513
513
  "Requestor_mobilize(test)/base2.out" for target sheets.
514
514
 
data/Rakefile CHANGED
@@ -17,7 +17,7 @@ require "bundler/gem_tasks"
17
17
  # Setup
18
18
  #
19
19
  $LOAD_PATH.unshift 'lib'
20
- require 'mobilize-base/rakes'
20
+ require 'mobilize-base/tasks'
21
21
 
22
22
  #
23
23
  # Tests
data/lib/mobilize-base.rb CHANGED
@@ -66,7 +66,7 @@ if File.exists?(mongoid_config_path)
66
66
  require "mobilize-base/models/user"
67
67
  require "mobilize-base/models/runner"
68
68
  require "mobilize-base/models/job"
69
- require "mobilize-base/models/task"
69
+ require "mobilize-base/models/stage"
70
70
  end
71
71
  require 'google_drive'
72
72
  require 'resque'
@@ -137,8 +137,9 @@ module GoogleDrive
137
137
  if loc_v != rem_v
138
138
  if ['true','false'].include?(loc_v.downcase)
139
139
  #google sheet upcases true and false. ignore
140
- elsif loc_v.starts_with?('rp') and rem_v.starts_with?('Rp')
141
- # some other math bs
140
+ elsif loc_v.to_s.downcase.gsub("-","").gsub(" ","")==rem_v.to_s.downcase.gsub("-","").gsub(" ","")
141
+ #supported currency, silently converted whether it's an actual currency or not
142
+ #put a backtick on it.
142
143
  sheet[row_i+1,col_i+1] = %{'#{loc_v}}
143
144
  re_col_vs << {'row_i'=>row_i+1,'col_i'=>col_i+1,'col_v'=>%{'#{loc_v}}}
144
145
  elsif (loc_v.to_s.count('e')==1 or loc_v.to_s.count('e')==0) and
@@ -22,12 +22,12 @@ module Mobilize
22
22
  Gdrive.files(gdrive_slot,{"title"=>path,"title-exact"=>"true"}).first
23
23
  end
24
24
 
25
- def Gfile.read_by_task_path(task_path)
25
+ def Gfile.read_by_stage_path(stage_path)
26
26
  #reserve gdrive_slot account for read
27
- gdrive_slot = Gdrive.slot_worker_by_path(t.path)
27
+ gdrive_slot = Gdrive.slot_worker_by_path(s.path)
28
28
  return false unless gdrive_slot
29
- t = Task.where(:path=>task_path)
30
- gfile_path = t.params['file']
29
+ s = Stage.where(:path=>stage_path)
30
+ gfile_path = s.params['file']
31
31
  Gfile.find_by_path(gfile_path,gdrive_slot).read
32
32
  end
33
33
  end
@@ -32,32 +32,32 @@ module Mobilize
32
32
  return sheet
33
33
  end
34
34
 
35
- def Gsheet.read_by_task_path(task_path)
35
+ def Gsheet.read_by_stage_path(stage_path)
36
36
  #reserve gdrive_slot account for read
37
- gdrive_slot = Gdrive.slot_worker_by_path(task_path)
37
+ gdrive_slot = Gdrive.slot_worker_by_path(stage_path)
38
38
  return false unless gdrive_slot
39
- t = Task.where(:path=>task_path).first
40
- gsheet_path = t.params['source']
39
+ s = Stage.where(:path=>stage_path).first
40
+ gsheet_path = s.params['source']
41
41
  Gsheet.find_by_path(gsheet_path,gdrive_slot).to_tsv
42
42
  end
43
43
 
44
- def Gsheet.write_by_task_path(task_path)
45
- gdrive_slot = Gdrive.slot_worker_by_path(task_path)
44
+ def Gsheet.write_by_stage_path(stage_path)
45
+ gdrive_slot = Gdrive.slot_worker_by_path(stage_path)
46
46
  #return false if there are no emails available
47
47
  return false unless gdrive_slot
48
- t = Task.where(:path=>task_path).first
49
- source = t.params['source']
50
- target_path = t.params['target']
51
- source_job_name, source_task_name = if source.index("/")
48
+ s = Stage.where(:path=>stage_path).first
49
+ source = s.params['source']
50
+ target_path = s.params['target']
51
+ source_job_name, source_stage_name = if source.index("/")
52
52
  source.split("/")
53
53
  else
54
54
  [nil, source]
55
55
  end
56
- source_task_path = "#{t.job.runner.path}/#{source_job_name || t.job.name}/#{source_task_name}"
57
- source_task = Task.where(:path=>source_task_path).first
58
- tsv = source_task.stdout_dataset.read_cache
56
+ source_stage_path = "#{s.job.runner.path}/#{source_job_name || s.job.name}/#{source_stage_name}"
57
+ source_stage = Stage.where(:path=>source_stage_path).first
58
+ tsv = source_stage.stdout_dataset.read_cache
59
59
  sheet_name = target_path.split("/").last
60
- temp_path = [task_path.gridsafe,sheet_name].join("/")
60
+ temp_path = [stage_path.gridsafe,sheet_name].join("/")
61
61
  temp_sheet = Gsheet.find_or_create_by_path(temp_path,gdrive_slot)
62
62
  temp_sheet.write(tsv)
63
63
  temp_sheet.check_and_fix(tsv)
@@ -50,7 +50,7 @@ module Mobilize
50
50
  end
51
51
 
52
52
  def Resque.active_paths
53
- #first argument of the payload is the runner / task path unless the worker is Jobtracker
53
+ #first argument of the payload is the runner / stage path unless the worker is Jobtracker
54
54
  Resque.jobs('active').map{|j| j['args'].first unless j['class']=='Jobtracker'}.compact
55
55
  end
56
56
 
@@ -190,7 +190,9 @@ module Mobilize
190
190
  while Jobtracker.status != 'stopping'
191
191
  users = User.all
192
192
  Jobtracker.run_notifications
193
- users.each do |u|
193
+ #run throush all users randomly
194
+ #so none are privileged on JT restarts
195
+ users.sort_by{rand}.each do |u|
194
196
  r = u.runner
195
197
  Jobtracker.update_status("Checking #{r.path}")
196
198
  if r.is_due?
@@ -13,9 +13,9 @@ module Mobilize
13
13
  j.path.split("/").last
14
14
  end
15
15
 
16
- def tasks
16
+ def stages
17
17
  j = self
18
- Task.where(:path=>/^#{j.path.escape_regex}/).to_a.sort_by{|t| t.path}
18
+ Stage.where(:path=>/^#{j.path.escape_regex}/).to_a.sort_by{|s| s.path}
19
19
  end
20
20
 
21
21
  def Job.find_or_create_by_path(path)
@@ -25,29 +25,30 @@ module Mobilize
25
25
  end
26
26
 
27
27
  def status
28
- #last task status
28
+ #last stage status
29
29
  j = self
30
- j.active_task.status
30
+ j.active_stage.status if j.active_stage
31
31
  end
32
32
 
33
- def active_task
33
+ def active_stage
34
34
  j = self
35
35
  #latest started at or first
36
- j.tasks.select{|t| t.started_at}.sort_by{|t| t.started_at}.last || j.tasks.first
36
+ j.stages.select{|s| s.started_at}.sort_by{|s| s.started_at}.last || j.stages.first
37
37
  end
38
38
 
39
39
  def completed_at
40
40
  j = self
41
- j.tasks.last.completed_at
41
+ j.stages.last.completed_at if j.stages.last
42
42
  end
43
43
 
44
44
  def failed_at
45
45
  j = self
46
- j.tasks.last.failed_at
46
+ j.active_stage.failed_at if j.active_stage
47
47
  end
48
48
 
49
49
  def status_at
50
- j.active_task.status_at
50
+ j = self
51
+ j.active_stage.status_at if j.active_stage
51
52
  end
52
53
 
53
54
  #convenience methods
@@ -59,7 +60,7 @@ module Mobilize
59
60
 
60
61
  def is_working?
61
62
  j = self
62
- j.tasks.select{|t| t.is_working?}.compact.length>0
63
+ j.stages.select{|s| s.is_working?}.compact.length>0
63
64
  end
64
65
 
65
66
  def is_due?
@@ -12,7 +12,7 @@ module Mobilize
12
12
  index({ path: 1})
13
13
 
14
14
  def headers
15
- %w{name active trigger status task1 task2 task3 task4 task5}
15
+ %w{name active trigger status stage1 stage2 stage3 stage4 stage5}
16
16
  end
17
17
 
18
18
  def cached_at
@@ -41,6 +41,7 @@ module Mobilize
41
41
  r.update_status("no gdrive slot available")
42
42
  return false
43
43
  end
44
+ r.update_attributes(:started_at=>Time.now.utc)
44
45
  #make sure any updates to activity are processed first
45
46
  #as in when someone runs a "once" job that has completed
46
47
  r.update_gsheet(gdrive_slot)
@@ -50,7 +51,7 @@ module Mobilize
50
51
  r.jobs.each do |j|
51
52
  begin
52
53
  if j.is_due?
53
- j.tasks.first.enqueue!
54
+ j.stages.first.enqueue!
54
55
  end
55
56
  rescue ScriptError, StandardError => exc
56
57
  r.update_status("Failed to enqueue #{j.path} with #{exc.to_s}")
@@ -95,25 +96,25 @@ module Mobilize
95
96
  #parse out the jobs and update the Job collection
96
97
  gsheet_jobs.each_with_index do |rj,rj_i|
97
98
  #skip non-jobs or jobs without required values
98
- next if (rj['name'].to_s.first == "#" or ['name','active','trigger','task1'].select{|c| rj[c].to_s.strip==""}.length>0)
99
+ next if (rj['name'].to_s.first == "#" or ['name','active','trigger','stage1'].select{|c| rj[c].to_s.strip==""}.length>0)
99
100
  j = Job.find_or_create_by_path("#{r.path}/#{rj['name']}")
100
101
  #update top line params
101
102
  j.update_attributes(:active => rj['active'],
102
103
  :trigger => rj['trigger'])
103
- (1..5).to_a.each do |t_idx|
104
- task_string = rj["task#{t_idx.to_s}"]
105
- break if task_string.to_s.length==0
106
- t = Task.find_or_create_by_path("#{j.path}/task#{t_idx.to_s}")
107
- #parse command string, update task with it
108
- t_handler, call, param_string = [""*3]
109
- task_string.split(" ").ie do |spls|
110
- t_handler = spls.first.split(".").first
104
+ (1..5).to_a.each do |s_idx|
105
+ stage_string = rj["stage#{s_idx.to_s}"]
106
+ break if stage_string.to_s.length==0
107
+ s = Stage.find_or_create_by_path("#{j.path}/stage#{s_idx.to_s}")
108
+ #parse command string, update stage with it
109
+ s_handler, call, param_string = [""*3]
110
+ stage_string.split(" ").ie do |spls|
111
+ s_handler = spls.first.split(".").first
111
112
  call = spls.first.split(".").last
112
113
  param_string = spls[1..-1].join(" ").strip
113
114
  end
114
- t.update_attributes(:call=>call, :handler=>t_handler, :param_string=>param_string)
115
+ s.update_attributes(:call=>call, :handler=>s_handler, :param_string=>param_string)
115
116
  end
116
- r.update_status("Updated #{j.path} tasks at #{Time.now.utc}")
117
+ r.update_status("Updated #{j.path} stages at #{Time.now.utc}")
117
118
  #add this job to list of read ones
118
119
  done_jobs << j
119
120
  end
@@ -130,11 +131,7 @@ module Mobilize
130
131
  def update_gsheet(gdrive_slot)
131
132
  r = self
132
133
  jobs_gsheet = r.gsheet(gdrive_slot)
133
- upd_jobs = r.jobs.select do |j|
134
- j.completed_at.nil? ||
135
- j.completed_at > j.runner.completed_at ||
136
- (j.failed_at and j.failed_at > j.runner.completed_at)
137
- end
134
+ upd_jobs = r.jobs.select{|j| j.status_at and j.status_at > j.runner.completed_at}
138
135
  upd_rows = upd_jobs.map{|j| {'name'=>j.name, 'active'=>j.active, 'status'=>j.status}}
139
136
  jobs_gsheet.add_or_update_rows(upd_rows)
140
137
  r.update_status("gsheet updated")
@@ -178,7 +175,6 @@ module Mobilize
178
175
 
179
176
  def enqueue!
180
177
  r = self
181
- r.update_attributes(:started_at=>Time.now.utc)
182
178
  ::Resque::Job.create("mobilize",Runner,r.path,{})
183
179
  return true
184
180
  end
@@ -0,0 +1,153 @@
1
+ module Mobilize
2
+ class Stage
3
+ include Mongoid::Document
4
+ include Mongoid::Timestamps
5
+ field :path, type: String
6
+ field :handler, type: String
7
+ field :call, type: String
8
+ field :param_string, type: Array
9
+ field :status, type: String
10
+ field :completed_at, type: Time
11
+ field :started_at, type: Time
12
+ field :failed_at, type: Time
13
+ field :status_at, type: Time
14
+
15
+ index({ path: 1})
16
+
17
+ def idx
18
+ s = self
19
+ s.path.split("/").last.gsub("stage","").to_i
20
+ end
21
+
22
+ def stdout_dataset
23
+ s = self
24
+ Dataset.find_or_create_by_handler_and_path("gridfs","#{s.path}/stdout")
25
+ end
26
+
27
+ def stderr_dataset
28
+ s = self
29
+ Dataset.find_or_create_by_handler_and_path("gridfs","#{s.path}/stderr")
30
+ end
31
+
32
+ def log_dataset
33
+ s = self
34
+ Dataset.find_or_create_by_handler_and_path("gridfs","#{s.path}/log")
35
+ end
36
+
37
+ def params
38
+ s = self
39
+ #evaluates param_string to ruby hash
40
+ #using YAML parser
41
+ #TODO: eliminate ridiculousness
42
+ begin
43
+ YAML.load(s.param_string)
44
+ raise "Must resolve to Hash" unless result.class==Hash
45
+ rescue
46
+ sub_param_string = s.param_string.gsub(":\"",": \"").gsub(":'",": '").gsub(":[",": [").gsub(":{",": {").gsub(/(:[0-9])/,'stageparamsgsub\1').gsub('stageparamsgsub:',': ')
47
+ YAML.load("{#{sub_param_string}}")
48
+ end
49
+ end
50
+
51
+ def job
52
+ s = self
53
+ job_path = s.path.split("/")[0..-2].join("/")
54
+ Job.where(:path=>job_path).first
55
+ end
56
+
57
+ def Stage.find_or_create_by_path(path)
58
+ s = Stage.where(:path=>path).first
59
+ s = Stage.create(:path=>path) unless s
60
+ return s
61
+ end
62
+
63
+ def prior
64
+ s = self
65
+ j = s.job
66
+ return nil if s.idx==1
67
+ return j.stages[s.idx-2]
68
+ end
69
+
70
+ def next
71
+ s = self
72
+ j = s.job
73
+ return nil if s.idx == j.stages.length
74
+ return j.stages[s.idx]
75
+ end
76
+
77
+ def Stage.perform(id,*args)
78
+ s = Stage.where(:path=>id).first
79
+ j = s.job
80
+ s.update_attributes(:started_at=>Time.now.utc)
81
+ s.update_status(%{Starting at #{Time.now.utc}})
82
+ stdout, stderr = [nil,nil]
83
+ begin
84
+ stdout,log = "Mobilize::#{s.handler.humanize}".constantize.send("#{s.call}_by_stage_path",s.path).to_s
85
+ #write to log if method returns an array w 2 members
86
+ s.log_dataset.write_cache(log) if log
87
+ rescue ScriptError, StandardError => exc
88
+ stderr = [exc.to_s,exc.backtrace.to_s].join("\n")
89
+ #record the failure in Job so it appears on Runner, turn it off
90
+ #so it doesn't run again
91
+ j.update_attributes(:active=>false)
92
+ s.update_attributes(:failed_at=>Time.now.utc)
93
+ s.update_status("Failed at #{Time.now.utc.to_s}")
94
+ raise exc
95
+ end
96
+ if stdout == false
97
+ #re-queue self if output is false
98
+ s.enqueue!
99
+ return false
100
+ end
101
+ #write output to cache
102
+ s.stdout_dataset.write_cache(stdout)
103
+ s.update_attributes(:completed_at=>Time.now.utc)
104
+ s.update_status("Completed at #{Time.now.utc.to_s}")
105
+ if s.idx == j.stages.length
106
+ #job has completed
107
+ j.update_attributes(:active=>false) if j.trigger.strip.downcase == "once"
108
+ #check for any dependent jobs, if there are, enqueue them
109
+ r = j.runner
110
+ dep_jobs = r.jobs.select{|dj| dj.active==true and dj.trigger.strip.downcase == "after #{j.name}"}
111
+ #put begin/rescue so all dependencies run
112
+ dep_jobs.each{|dj| begin;dj.stages.first.enqueue! unless dj.is_working?;rescue;end}
113
+ else
114
+ #queue up next stage
115
+ s.next.enqueue!
116
+ end
117
+ return true
118
+ end
119
+
120
+ def enqueue!
121
+ s = self
122
+ ::Resque::Job.create("mobilize",Stage,s.path,{})
123
+ return true
124
+ end
125
+
126
+ def worker
127
+ s = self
128
+ Mobilize::Resque.find_worker_by_path(s.path)
129
+ end
130
+
131
+ def worker_args
132
+ s = self
133
+ Jobtracker.get_worker_args(s.worker)
134
+ end
135
+
136
+ def set_worker_args(args)
137
+ s = self
138
+ Jobtracker.set_worker_args(s.worker,args)
139
+ end
140
+
141
+ def update_status(msg)
142
+ s = self
143
+ s.update_attributes(:status=>msg,:status_at=>Time.now.utc)
144
+ Mobilize::Resque.set_worker_args_by_path(s.path,{'status'=>msg})
145
+ return true
146
+ end
147
+
148
+ def is_working?
149
+ s = self
150
+ Mobilize::Resque.active_paths.include?(s.path)
151
+ end
152
+ end
153
+ end
@@ -35,6 +35,21 @@ namespace :mobilize_base do
35
35
  require 'mobilize-base'
36
36
  Mobilize::Jobtracker.prep_workers
37
37
  end
38
+ desc "Stop Jobtracker"
39
+ task :stop do
40
+ require 'mobilize-base'
41
+ Mobilize::Jobtracker.stop!
42
+ end
43
+ desc "Start Jobtracker"
44
+ task :start do
45
+ require 'mobilize-base'
46
+ Mobilize::Jobtracker.start
47
+ end
48
+ desc "Restart Jobtracker"
49
+ task :restart do
50
+ require 'mobilize-base'
51
+ Mobilize::Jobtracker.restart!
52
+ end
38
53
  desc "kill all old resque web processes, start new one with resque_web.rb extension file"
39
54
  task :resque_web do
40
55
  require 'mobilize-base'
@@ -1,5 +1,5 @@
1
1
  module Mobilize
2
2
  module Base
3
- VERSION = "1.0.75"
3
+ VERSION = "1.0.81"
4
4
  end
5
5
  end
@@ -0,0 +1,3 @@
1
+ - {test_header: s1, test_header2: s1, test_header3: s1}
2
+ - {test_header: s2, test_header2: s2, test_header3: s2}
3
+ - {test_header: s3, test_header2: s3, test_header3: s3}
@@ -2,12 +2,12 @@
2
2
  active: true
3
3
  trigger: once
4
4
  status: ""
5
- task1: 'gsheet.read source:"Runner_mobilize(test)/base1_task1.in"'
6
- task2: 'gsheet.write source:"base1/task1", target:"Runner_mobilize(test)/base1.out"'
5
+ stage1: 'gsheet.read source:"Runner_mobilize(test)/base1_stage1.in"'
6
+ stage2: 'gsheet.write source:"base1/stage1", target:"Runner_mobilize(test)/base1.out"'
7
7
 
8
8
  - name: "base2"
9
9
  active: true
10
10
  trigger: "after base1"
11
11
  status: ""
12
- task1: 'gsheet.read source:"Runner_mobilize(test)/base1.out"'
13
- task2: 'gsheet.write source:"task1", target:"Runner_mobilize(test)/base2.out"'
12
+ stage1: 'gsheet.read source:"Runner_mobilize(test)/base1.out"'
13
+ stage2: 'gsheet.write source:"stage1", target:"Runner_mobilize(test)/base2.out"'
@@ -32,12 +32,12 @@ describe "Mobilize" do
32
32
  r = u.runner
33
33
  jobs_sheet = r.gsheet(gdrive_slot)
34
34
  tsv = jobs_sheet.to_tsv
35
- assert tsv.length == 56 #headers only
35
+ assert tsv.length == 61 #headers only
36
36
 
37
- puts "add base1_task1 input sheet"
38
- test_source_sheet = Mobilize::Gsheet.find_or_create_by_path("#{r.path.split("/")[0..-2].join("/")}/base1_task1.in",gdrive_slot)
37
+ puts "add base1_stage1 input sheet"
38
+ test_source_sheet = Mobilize::Gsheet.find_or_create_by_path("#{r.path.split("/")[0..-2].join("/")}/base1_stage1.in",gdrive_slot)
39
39
 
40
- test_source_ha = ::YAML.load_file("#{Mobilize::Base.root}/test/base1_task1.yml")*40
40
+ test_source_ha = ::YAML.load_file("#{Mobilize::Base.root}/test/base1_stage1.yml")*40
41
41
  test_source_tsv = test_source_ha.hash_array_to_tsv
42
42
  test_source_sheet.write(test_source_tsv)
43
43
 
@@ -48,13 +48,12 @@ describe "Mobilize" do
48
48
 
49
49
  puts "jobtracker posted test sheet data to test destination, and checksum succeeded?"
50
50
  test_target_sheet_1 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/base1.out",gdrive_slot)
51
- test_target_sheet_1 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/base1.out",gdrive_slot)
52
-
51
+ test_target_sheet_2 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/base2.out",gdrive_slot)
53
52
 
54
53
  assert test_target_sheet_1.to_tsv == test_source_sheet.to_tsv
55
54
 
56
55
  puts "delete both output sheets, set first job to active=true"
57
- test_target_sheet_1.delete
56
+ [test_target_sheet_1,test_target_sheet_2].each{|s| s.delete}
58
57
 
59
58
  jobs_sheet.add_or_update_rows([{'name'=>'base1','active'=>true}])
60
59
  sleep 90
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mobilize-base
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.75
4
+ version: 1.0.81
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-15 00:00:00.000000000 Z
12
+ date: 2012-12-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -207,9 +207,9 @@ files:
207
207
  - lib/mobilize-base/models/dataset.rb
208
208
  - lib/mobilize-base/models/job.rb
209
209
  - lib/mobilize-base/models/runner.rb
210
- - lib/mobilize-base/models/task.rb
210
+ - lib/mobilize-base/models/stage.rb
211
211
  - lib/mobilize-base/models/user.rb
212
- - lib/mobilize-base/rakes.rb
212
+ - lib/mobilize-base/tasks.rb
213
213
  - lib/mobilize-base/version.rb
214
214
  - lib/samples/gdrive.yml
215
215
  - lib/samples/gridfs.yml
@@ -219,7 +219,7 @@ files:
219
219
  - lib/samples/resque.yml
220
220
  - lib/samples/resque_web.rb
221
221
  - mobilize-base.gemspec
222
- - test/base1_task1.yml
222
+ - test/base1_stage1.yml
223
223
  - test/base_job_rows.yml
224
224
  - test/mobilize-base_test.rb
225
225
  - test/redis-test.conf
@@ -238,7 +238,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
238
238
  version: '0'
239
239
  segments:
240
240
  - 0
241
- hash: 2930191387184106525
241
+ hash: -1990483530432854751
242
242
  required_rubygems_version: !ruby/object:Gem::Requirement
243
243
  none: false
244
244
  requirements:
@@ -247,7 +247,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
247
247
  version: '0'
248
248
  segments:
249
249
  - 0
250
- hash: 2930191387184106525
250
+ hash: -1990483530432854751
251
251
  requirements: []
252
252
  rubyforge_project: mobilize-base
253
253
  rubygems_version: 1.8.24
@@ -256,7 +256,7 @@ specification_version: 3
256
256
  summary: Moves datasets and schedules data transfers using MongoDB, Resque and Google
257
257
  Docs
258
258
  test_files:
259
- - test/base1_task1.yml
259
+ - test/base1_stage1.yml
260
260
  - test/base_job_rows.yml
261
261
  - test/mobilize-base_test.rb
262
262
  - test/redis-test.conf
@@ -1,154 +0,0 @@
1
- module Mobilize
2
- class Task
3
- include Mongoid::Document
4
- include Mongoid::Timestamps
5
- field :path, type: String
6
- field :handler, type: String
7
- field :call, type: String
8
- field :param_string, type: Array
9
- field :status, type: String
10
- field :completed_at, type: Time
11
- field :started_at, type: Time
12
- field :failed_at, type: Time
13
- field :status_at, type: Time
14
-
15
- index({ path: 1})
16
-
17
- def idx
18
- t = self
19
- t.path.split("/").last.gsub("task","").to_i
20
- end
21
-
22
- def stdout_dataset
23
- t = self
24
- Dataset.find_or_create_by_handler_and_path("gridfs","#{t.path}/stdout")
25
- end
26
-
27
- def stderr_dataset
28
- t = self
29
- Dataset.find_or_create_by_handler_and_path("gridfs","#{t.path}/stderr")
30
- end
31
-
32
- def log_dataset
33
- t = self
34
- Dataset.find_or_create_by_handler_and_path("gridfs","#{t.path}/log")
35
- end
36
-
37
- def params
38
- t = self
39
- #evaluates param_string to ruby hash
40
- #using YAML parser
41
- #TODO: eliminate ridiculousness
42
- begin
43
- YAML.load(t.param_string)
44
- raise "Must resolve to Hash" unless result.class==Hash
45
- rescue
46
- sub_param_string = t.param_string.gsub(":\"",": \"").gsub(":'",": '").gsub(":[",": [").gsub(":{",": {").gsub(/(:[0-9])/,'taskparamsgsub\1').gsub('taskparamsgsub:',': ')
47
- YAML.load("{#{sub_param_string}}")
48
- end
49
- end
50
-
51
- def job
52
- t = self
53
- job_path = t.path.split("/")[0..-2].join("/")
54
- Job.where(:path=>job_path).first
55
- end
56
-
57
- def Task.find_or_create_by_path(path)
58
- t = Task.where(:path=>path).first
59
- t = Task.create(:path=>path) unless t
60
- return t
61
- end
62
-
63
- def prior
64
- t = self
65
- j = t.job
66
- return nil if t.idx==1
67
- return j.tasks[t.idx-2]
68
- end
69
-
70
- def next
71
- t = self
72
- j = t.job
73
- return nil if t.idx == j.tasks.length
74
- return j.tasks[t.idx]
75
- end
76
-
77
- def Task.perform(id,*args)
78
- t = Task.where(:path=>id).first
79
- j = t.job
80
- t.update_status(%{Starting at #{Time.now.utc}})
81
- stdout, stderr = [nil,nil]
82
- begin
83
- stdout,log = "Mobilize::#{t.handler.humanize}".constantize.send("#{t.call}_by_task_path",t.path).to_s
84
- #write to log if method returns an array w 2 members
85
- t.log_dataset.write_cache(log) if log
86
- rescue ScriptError, StandardError => exc
87
- stderr = [exc.to_s,exc.backtrace.to_s].join("\n")
88
- #record the failure in Job so it appears on Runner, turn it off
89
- #so it doesn't run again
90
- j.update_attributes(:active=>false)
91
- t.update_attributes(:failed_at=>Time.now.utc)
92
- t.update_status("Failed at #{Time.now.utc.to_s}")
93
- raise exc
94
- end
95
- if stdout == false
96
- #re-queue self if output is false
97
- t.enqueue!
98
- return false
99
- end
100
- #write output to cache
101
- t.stdout_dataset.write_cache(stdout)
102
- t.update_attributes(:status=>"Completed at #{Time.now.utc.to_s}")
103
- if t.idx == j.tasks.length
104
- #job has completed
105
- j.update_attributes(:active=>false) if j.trigger.strip.downcase == "once"
106
- t.update_attributes(:completed_at=>Time.now.utc)
107
- t.update_status("Completed at #{Time.now.utc.to_s}")
108
- #check for any dependent jobs, if there are, enqueue them
109
- r = j.runner
110
- dep_jobs = r.jobs.select{|dj| dj.active==true and dj.trigger.strip.downcase == "after #{j.name}"}
111
- #put begin/rescue so all dependencies run
112
- dep_jobs.each{|dj| begin;dj.tasks.first.enqueue! unless dj.is_working?;rescue;end}
113
- else
114
- #queue up next task
115
- t.next.enqueue!
116
- end
117
- return true
118
- end
119
-
120
- def enqueue!
121
- t = self
122
- t.update_attributes(:started_at=>Time.now.utc)
123
- ::Resque::Job.create("mobilize",Task,t.path,{})
124
- return true
125
- end
126
-
127
- def worker
128
- t = self
129
- Mobilize::Resque.find_worker_by_path(t.path)
130
- end
131
-
132
- def worker_args
133
- t = self
134
- Jobtracker.get_worker_args(t.worker)
135
- end
136
-
137
- def set_worker_args(args)
138
- t = self
139
- Jobtracker.set_worker_args(t.worker,args)
140
- end
141
-
142
- def update_status(msg)
143
- t = self
144
- t.update_attributes(:status=>msg,:status_at=>Time.now.utc)
145
- Mobilize::Resque.set_worker_args_by_path(t.path,{'status'=>msg})
146
- return true
147
- end
148
-
149
- def is_working?
150
- t = self
151
- Mobilize::Resque.active_paths.include?(t.path)
152
- end
153
- end
154
- end
data/test/base1_task1.yml DELETED
@@ -1,3 +0,0 @@
1
- - {test_header: t1, test_header2: t1, test_header3: t1}
2
- - {test_header: t2, test_header2: t2, test_header3: t2}
3
- - {test_header: t3, test_header2: t3, test_header3: t3}