mobilize-base 1.36 → 1.293
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +666 -1
- data/lib/mobilize-base.rb +1 -12
- data/lib/mobilize-base/extensions/array.rb +3 -8
- data/lib/mobilize-base/extensions/google_drive/acl.rb +1 -1
- data/lib/mobilize-base/extensions/google_drive/client_login_fetcher.rb +1 -2
- data/lib/mobilize-base/extensions/google_drive/file.rb +37 -11
- data/lib/mobilize-base/extensions/string.rb +6 -11
- data/lib/mobilize-base/extensions/yaml.rb +7 -10
- data/lib/mobilize-base/handlers/gbook.rb +38 -25
- data/lib/mobilize-base/handlers/gdrive.rb +4 -20
- data/lib/mobilize-base/handlers/gfile.rb +10 -64
- data/lib/mobilize-base/handlers/gridfs.rb +24 -19
- data/lib/mobilize-base/handlers/gsheet.rb +29 -45
- data/lib/mobilize-base/handlers/resque.rb +10 -17
- data/lib/mobilize-base/jobtracker.rb +196 -22
- data/lib/mobilize-base/models/job.rb +77 -107
- data/lib/mobilize-base/models/runner.rb +122 -36
- data/lib/mobilize-base/models/stage.rb +37 -18
- data/lib/mobilize-base/tasks.rb +13 -50
- data/lib/mobilize-base/version.rb +1 -1
- data/lib/samples/gdrive.yml +0 -15
- data/lib/samples/gridfs.yml +3 -0
- data/lib/samples/gsheet.yml +4 -4
- data/lib/samples/jobtracker.yml +6 -0
- data/mobilize-base.gemspec +3 -3
- data/test/base_job_rows.yml +11 -0
- data/test/mobilize-base_test.rb +106 -0
- data/test/test_base_1.yml +3 -0
- data/test/test_helper.rb +0 -155
- metadata +24 -36
- data/lib/mobilize-base/extensions/time.rb +0 -20
- data/lib/mobilize-base/helpers/job_helper.rb +0 -54
- data/lib/mobilize-base/helpers/jobtracker_helper.rb +0 -143
- data/lib/mobilize-base/helpers/runner_helper.rb +0 -83
- data/lib/mobilize-base/helpers/stage_helper.rb +0 -38
- data/lib/samples/gfile.yml +0 -9
- data/test/fixtures/base1_stage1.in.yml +0 -10
- data/test/fixtures/integration_expected.yml +0 -25
- data/test/fixtures/integration_jobs.yml +0 -12
- data/test/fixtures/is_due.yml +0 -97
- data/test/integration/mobilize-base_test.rb +0 -57
- data/test/unit/mobilize-base_test.rb +0 -33
@@ -1,83 +0,0 @@
|
|
1
|
-
#this module adds convenience methods to the Runner model
|
2
|
-
module Mobilize
|
3
|
-
module RunnerHelper
|
4
|
-
def headers
|
5
|
-
%w{name active trigger status stage1 stage2 stage3 stage4 stage5}
|
6
|
-
end
|
7
|
-
|
8
|
-
def title
|
9
|
-
r = self
|
10
|
-
r.path.split("/").first
|
11
|
-
end
|
12
|
-
|
13
|
-
def worker
|
14
|
-
r = self
|
15
|
-
Mobilize::Resque.find_worker_by_path(r.path)
|
16
|
-
end
|
17
|
-
|
18
|
-
def dataset
|
19
|
-
r = self
|
20
|
-
Dataset.find_or_create_by_handler_and_path("gsheet",r.path)
|
21
|
-
end
|
22
|
-
|
23
|
-
def gbook(gdrive_slot)
|
24
|
-
r = self
|
25
|
-
title = r.path.split("/").first
|
26
|
-
Gbook.find_by_path(title,gdrive_slot)
|
27
|
-
end
|
28
|
-
|
29
|
-
def gsheet(gdrive_slot)
|
30
|
-
r = self
|
31
|
-
u = r.user
|
32
|
-
jobs_sheet = Gsheet.find_by_path(r.path,gdrive_slot)
|
33
|
-
#make sure the user has a runner with a jobs sheet and has write privileges on the spreadsheet
|
34
|
-
unless (jobs_sheet and jobs_sheet.spreadsheet.acl_entry(u.email).ie{|e| e and e.role=="writer"})
|
35
|
-
#only give the user edit permissions if they're the ones
|
36
|
-
#creating it
|
37
|
-
jobs_sheet = Gsheet.find_or_create_by_path(r.path,gdrive_slot)
|
38
|
-
unless jobs_sheet.spreadsheet.acl_entry(u.email).ie{|e| e and e.role=="owner"}
|
39
|
-
jobs_sheet.spreadsheet.update_acl(u.email)
|
40
|
-
end
|
41
|
-
jobs_sheet.add_headers(r.headers)
|
42
|
-
begin;jobs_sheet.delete_sheet1;rescue;end #don't care if sheet1 deletion fails
|
43
|
-
end
|
44
|
-
return jobs_sheet
|
45
|
-
end
|
46
|
-
|
47
|
-
def jobs(jname=nil)
|
48
|
-
r = self
|
49
|
-
js = Job.where(:path=>/^#{r.path.escape_regex}/).to_a
|
50
|
-
if jname
|
51
|
-
return js.sel{|j| j.name == jname}.first
|
52
|
-
else
|
53
|
-
return js
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def user
|
58
|
-
r = self
|
59
|
-
user_name = r.path.split("_")[1..-1].join("_").split("(").first.split("/").first
|
60
|
-
User.where(:name=>user_name).first
|
61
|
-
end
|
62
|
-
|
63
|
-
def update_status(msg)
|
64
|
-
r = self
|
65
|
-
r.update_attributes(:status=>msg, :status_at=>Time.now.utc)
|
66
|
-
Mobilize::Resque.set_worker_args_by_path(r.path,{'status'=>msg})
|
67
|
-
return true
|
68
|
-
end
|
69
|
-
|
70
|
-
def is_working?
|
71
|
-
r = self
|
72
|
-
Mobilize::Resque.active_paths.include?(r.path)
|
73
|
-
end
|
74
|
-
|
75
|
-
def is_due?
|
76
|
-
r = self.reload
|
77
|
-
return false if r.is_working?
|
78
|
-
prev_due_time = Time.now.utc - Jobtracker.runner_read_freq
|
79
|
-
return true if r.started_at.nil? or r.started_at < prev_due_time
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|
83
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
#this module adds convenience methods to the Stage model
|
2
|
-
module Mobilize
|
3
|
-
module StageHelper
|
4
|
-
def idx
|
5
|
-
s = self
|
6
|
-
s.path.split("/").last.gsub("stage","").to_i
|
7
|
-
end
|
8
|
-
|
9
|
-
def out_dst
|
10
|
-
#this gives a dataset that points to the output
|
11
|
-
#allowing you to determine its size
|
12
|
-
#before committing to a read or write
|
13
|
-
s = self
|
14
|
-
Dataset.find_by_url(s.response['out_url']) if s.response and s.response['out_url']
|
15
|
-
end
|
16
|
-
|
17
|
-
def err_dst
|
18
|
-
#this gives a dataset that points to the output
|
19
|
-
#allowing you to determine its size
|
20
|
-
#before committing to a read or write
|
21
|
-
s = self
|
22
|
-
Dataset.find_by_url(s.response['err_url']) if s.response and s.response['err_url']
|
23
|
-
end
|
24
|
-
|
25
|
-
def params
|
26
|
-
s = self
|
27
|
-
p = YAML.easy_load(s.param_string)
|
28
|
-
raise "Must resolve to Hash" unless p.class==Hash
|
29
|
-
return p
|
30
|
-
end
|
31
|
-
|
32
|
-
def job
|
33
|
-
s = self
|
34
|
-
job_path = s.path.split("/")[0..-2].join("/")
|
35
|
-
Job.where(:path=>job_path).first
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/lib/samples/gfile.yml
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
---
|
2
|
-
- path: "jobtracker"
|
3
|
-
state: working
|
4
|
-
count: 1
|
5
|
-
confirmed_ats: []
|
6
|
-
- path: "Runner_mobilize(test)/jobs"
|
7
|
-
state: working
|
8
|
-
count: 2
|
9
|
-
confirmed_ats: []
|
10
|
-
- path: "Runner_mobilize(test)/jobs/base1/stage1"
|
11
|
-
state: working
|
12
|
-
count: 1
|
13
|
-
confirmed_ats: []
|
14
|
-
- path: "Runner_mobilize(test)/jobs/base1/stage2"
|
15
|
-
state: working
|
16
|
-
count: 1
|
17
|
-
confirmed_ats: []
|
18
|
-
- path: "Runner_mobilize(test)/jobs/base2/stage1"
|
19
|
-
state: working
|
20
|
-
count: 1
|
21
|
-
confirmed_ats: []
|
22
|
-
- path: "Runner_mobilize(test)/jobs/base2/stage1"
|
23
|
-
state: failed
|
24
|
-
count: 2
|
25
|
-
confirmed_ats: []
|
@@ -1,12 +0,0 @@
|
|
1
|
-
---
|
2
|
-
- name: base1
|
3
|
-
active: true
|
4
|
-
trigger: once
|
5
|
-
status: ""
|
6
|
-
stage1: gfile.write source:"gsheet://base1_stage1.in", target:"gfile://base1_stage1.out"
|
7
|
-
stage2: gsheet.write source:"gfile://base1_stage1.out", target:"gsheet://base1_stage2.out"
|
8
|
-
- name: base2
|
9
|
-
active: true
|
10
|
-
trigger: after base1
|
11
|
-
status: ""
|
12
|
-
stage1: gsheet.write source:"base1."_"", target:"base2_stage1.out"
|
data/test/fixtures/is_due.yml
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
---
|
2
|
-
- name: once_active
|
3
|
-
active: true
|
4
|
-
trigger: once
|
5
|
-
status: ""
|
6
|
-
stage1: gsheet.method source:"source", target:"target"
|
7
|
-
expected: true
|
8
|
-
- name: once_inactive
|
9
|
-
active: false
|
10
|
-
trigger: once
|
11
|
-
status: ""
|
12
|
-
stage1: gfile.method source:"source", target:"target"
|
13
|
-
expected: false
|
14
|
-
- name: 1h_comp_never
|
15
|
-
active: true
|
16
|
-
trigger: every 1.hour
|
17
|
-
status: ""
|
18
|
-
stage1: gsheet.method source:"source", target:"target"
|
19
|
-
expected: true
|
20
|
-
- name: 1h_comp_0.5h_ago
|
21
|
-
active: true
|
22
|
-
trigger: every 1.hour
|
23
|
-
status: ""
|
24
|
-
stage1: gsheet.method source:"source", target:"target"
|
25
|
-
completed_at: Time.now.utc - 1800.seconds
|
26
|
-
expected: false
|
27
|
-
- name: 1h_comp_1.5h_ago
|
28
|
-
active: true
|
29
|
-
trigger: every 1.hour
|
30
|
-
status: ""
|
31
|
-
stage1: gsheet.method source:"source", target:"target"
|
32
|
-
completed_at: Time.now.utc - 5400.seconds
|
33
|
-
expected: true
|
34
|
-
- name: 1h_aft45_comp_2_45_marks_ago
|
35
|
-
active: true
|
36
|
-
trigger: 'every 1.hour after 45'
|
37
|
-
status: ""
|
38
|
-
stage1: gsheet.method source:"source", target:"target"
|
39
|
-
completed_at: Time.at_marks_ago(2,'hour', '45')
|
40
|
-
expected: true
|
41
|
-
- name: 1h_aft45_comp_aft_1_45_mark_ago
|
42
|
-
active: true
|
43
|
-
trigger: 'every 1.hour after :45'
|
44
|
-
status: ""
|
45
|
-
stage1: gsheet.method source:"source", target:"target"
|
46
|
-
completed_at: Time.at_marks_ago(1,'hour', '45')
|
47
|
-
expected: false
|
48
|
-
- name: 1d_aft0135_comp_2_0135_marks_ago
|
49
|
-
active: true
|
50
|
-
trigger: 'every 1.day after 01:35'
|
51
|
-
status: ""
|
52
|
-
stage1: gsheet.method source:"source", target:"target"
|
53
|
-
completed_at: Time.at_marks_ago(2,'day', '0135')
|
54
|
-
expected: true
|
55
|
-
- name: 1d_aft0135_comp_1_0135_mark_ago
|
56
|
-
active: true
|
57
|
-
trigger: 'every 1.day after 0135'
|
58
|
-
status: ""
|
59
|
-
stage1: gsheet.method source:"source", target:"target"
|
60
|
-
completed_at: Time.at_marks_ago(1,'day', '0135')
|
61
|
-
expected: false
|
62
|
-
- name: 5d_aft0135_comp_5_0135_mark_ago
|
63
|
-
active: true
|
64
|
-
trigger: 'every 5.day after 01:35'
|
65
|
-
status: ""
|
66
|
-
stage1: gsheet.method source:"source", target:"target"
|
67
|
-
completed_at: Time.at_marks_ago(5,'day', '0135')
|
68
|
-
expected: false
|
69
|
-
- name: 5d_aft0135_comp_6_0135_mark_ago
|
70
|
-
active: true
|
71
|
-
trigger: 'every 5.day after 01:35'
|
72
|
-
status: ""
|
73
|
-
stage1: gsheet.method source:"source", target:"target"
|
74
|
-
completed_at: Time.at_marks_ago(6,'day', '0135')
|
75
|
-
expected: true
|
76
|
-
- name: parent_comp_child_fail
|
77
|
-
active: true
|
78
|
-
trigger: 'after once_inactive'
|
79
|
-
status: ""
|
80
|
-
stage1: gsheet.method source:"source", target:"target"
|
81
|
-
parent: {completed_at: Time.now.utc - 1.second}
|
82
|
-
failed_at: Time.now.utc
|
83
|
-
expected: true
|
84
|
-
- name: parent_comp_child_comp
|
85
|
-
active: true
|
86
|
-
trigger: 'after once_inactive'
|
87
|
-
status: ""
|
88
|
-
stage1: gsheet.method source:"source", target:"target"
|
89
|
-
parent: {completed_at: Time.now.utc - 1.second}
|
90
|
-
completed_at: Time.now.utc
|
91
|
-
expected: false
|
92
|
-
- name: missing_module
|
93
|
-
active: true
|
94
|
-
trigger: once
|
95
|
-
status: ""
|
96
|
-
stage1: handler.method source:"source", target:"target"
|
97
|
-
expected: false
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
describe Mobilize do
|
3
|
-
|
4
|
-
it "runs integration test" do
|
5
|
-
|
6
|
-
puts "restart test redis"
|
7
|
-
TestHelper.restart_test_redis
|
8
|
-
TestHelper.drop_test_db
|
9
|
-
|
10
|
-
puts "restart workers"
|
11
|
-
Mobilize::Jobtracker.restart_workers!
|
12
|
-
|
13
|
-
u = TestHelper.owner_user
|
14
|
-
r = u.runner
|
15
|
-
user_name = u.name
|
16
|
-
gdrive_slot = u.email
|
17
|
-
|
18
|
-
puts "build test runner"
|
19
|
-
TestHelper.build_test_runner(user_name)
|
20
|
-
assert Mobilize::Jobtracker.workers.length == Mobilize::Resque.config['max_workers'].to_i
|
21
|
-
|
22
|
-
puts "add base1_stage1.in sheet"
|
23
|
-
input_fixture_name = "base1_stage1.in"
|
24
|
-
input_target_url = "gsheet://#{r.title}/#{input_fixture_name}"
|
25
|
-
TestHelper.write_fixture(input_fixture_name, input_target_url, 'replace' => true)
|
26
|
-
|
27
|
-
puts "add jobs sheet with integration jobs"
|
28
|
-
jobs_fixture_name = "integration_jobs"
|
29
|
-
jobs_target_url = "gsheet://#{r.title}/jobs"
|
30
|
-
TestHelper.write_fixture(jobs_fixture_name, jobs_target_url, 'update' => true)
|
31
|
-
|
32
|
-
puts "wait for stages"
|
33
|
-
Mobilize::Jobtracker.start
|
34
|
-
#wait for stages to complete
|
35
|
-
expected_fixture_name = "integration_expected"
|
36
|
-
TestHelper.confirm_expected_jobs(expected_fixture_name)
|
37
|
-
#stop jobtracker
|
38
|
-
Mobilize::Jobtracker.stop!
|
39
|
-
|
40
|
-
puts "jobtracker posted test sheet data to test destination, and checksum succeeded?"
|
41
|
-
tsv_hash = {}
|
42
|
-
["base1_stage1.in", "base1_stage2.out"].each do |sheet_name|
|
43
|
-
url = "gsheet://#{r.title}/#{sheet_name}"
|
44
|
-
data = Mobilize::Dataset.read_by_url(url,user_name,gdrive_slot)
|
45
|
-
assert TestHelper.check_output(url, 'min_length' => 10) == true
|
46
|
-
tsv_hash[sheet_name] = data
|
47
|
-
end
|
48
|
-
|
49
|
-
assert tsv_hash["base1_stage2.out"] == tsv_hash["base1_stage1.in"]
|
50
|
-
|
51
|
-
err_url = "gsheet://#{r.title}/base2_stage1.err"
|
52
|
-
err_response = "Unable to parse stage params, make sure you don't have issues with your quotes, commas, or colons."
|
53
|
-
|
54
|
-
assert TestHelper.check_output(err_url, 'match' => err_response) == true
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
class TestUnit < MiniTest::Unit::TestCase
|
3
|
-
def setup
|
4
|
-
TestHelper.restart_test_redis
|
5
|
-
TestHelper.drop_test_db
|
6
|
-
end
|
7
|
-
|
8
|
-
#this test checks that several job triggers work as expected
|
9
|
-
def test_is_due
|
10
|
-
u = TestHelper.owner_user
|
11
|
-
job_hashes = TestHelper.load_fixture("is_due")
|
12
|
-
job_hashes.each do |jh|
|
13
|
-
job_path = "#{u.runner.path}/#{jh['name']}"
|
14
|
-
j = Mobilize::Job.find_or_create_by_path(job_path)
|
15
|
-
#update job params
|
16
|
-
j.update_from_hash(jh)
|
17
|
-
#apply the completed_at, failed at, and parent attributes where appropriate
|
18
|
-
if jh['completed_at']
|
19
|
-
j.stages.last.update_attributes(:completed_at=>eval(jh['completed_at']))
|
20
|
-
end
|
21
|
-
if jh['failed_at']
|
22
|
-
j.stages.last.update_attributes(:failed_at=>eval(jh['failed_at']))
|
23
|
-
end
|
24
|
-
if jh['parent']
|
25
|
-
j.parent.stages.last.update_attributes(:completed_at=>eval(jh['parent']['completed_at'])) if jh['parent']['completed_at']
|
26
|
-
j.parent.stages.last.update_attributes(:failed_at=>eval(jh['parent']['failed_at'])) if jh['parent']['failed_at']
|
27
|
-
end
|
28
|
-
expected = jh['expected']
|
29
|
-
#check if is_due
|
30
|
-
assert expected == j.is_due?
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|