mobilize-base 1.0.75 → 1.0.81

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/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}