kindly 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7008dc866f7e27d37c5a69ce8dad35bd6669b42e
4
- data.tar.gz: 0aefa9e87d7db75410d5999cee14b742d44cf30d
3
+ metadata.gz: 0e6a32b5242cdaa718ac34d75b5f0d4c216faa09
4
+ data.tar.gz: 6b9b08dc1282bd73a313e2841028eecaacc19433
5
5
  SHA512:
6
- metadata.gz: b97fef9801e31b8337007c1ca996f633b0487bf2590464fc038c6a21269c363a5d15c56b4d6cbf43c63802c92a985597f8f55268637434b2b9c6e3a06e810d57
7
- data.tar.gz: 6013ce5a2ffd0180dde7d9b0ece187b268077f406ac8ef2a45c5745b34aaee86c041479171d7d62920d79d2162c722b6eaa1326649fa0149e5d5de08d35cd283
6
+ metadata.gz: 62eabc59ec779bed01bbb72a4501d5b1492d9968dcfa7a70cd473558ac75863fe2fdf6a72d143ead6a590eac236e667e5b06ec90358444c6570394f6e6d5a87a
7
+ data.tar.gz: a3447e56fd04edef3ec992f85d362ad651a970b08291907367f18ed49ac1272c9b827a82042a46fd8866228f6d840518362da04127d9b81c627558d391e72388
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
+ .bundle
1
2
  Gemfile.lock
2
3
  pkg/
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rake/testtask'
3
+ require 'kindly'
3
4
 
4
5
  Rake::TestTask.new do |test|
5
6
  test.libs << 'lib' << 'test'
@@ -7,4 +8,34 @@ Rake::TestTask.new do |test|
7
8
  test.verbose = true
8
9
  end
9
10
 
11
+ desc 'Request test_job'
12
+ task :request_test_job do
13
+ Kindly.request :test_job
14
+ end
15
+
16
+ desc 'Request test_job_with_input'
17
+ task :request_test_job_with_input do
18
+ Kindly.request :test_job_with_input, 'hello'
19
+ end
20
+
21
+ desc 'Request test_job_with_output'
22
+ task :request_test_job_with_output do
23
+ Kindly.request :test_job_with_output
24
+ end
25
+
26
+ desc 'Run test_job'
27
+ task :run_test_job do
28
+ Kindly.run :test_job
29
+ end
30
+
31
+ desc 'Run test_job_with_input'
32
+ task :run_test_job_with_input do
33
+ Kindly.run :test_job_with_input
34
+ end
35
+
36
+ desc 'Run test_job_with_output'
37
+ task :run_test_job_with_output do
38
+ Kindly.run :test_job_with_output
39
+ end
40
+
10
41
  task :default => :test
data/kindly.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.version = Kindly::VERSION
10
10
  spec.authors = ['Greg Scott']
11
11
  spec.email = ['i@gregoryjscott.com']
12
- spec.summary = %q{Kindly run migrations of any kind.}
12
+ spec.summary = %q{Kindly run jobs of any kind.}
13
13
  spec.homepage = 'https://github.com/gregoryjscott/kindly'
14
14
  spec.license = 'MIT'
15
15
 
@@ -19,9 +19,11 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_runtime_dependency 'mercenary', '~> 0.3'
22
+ spec.add_runtime_dependency 'aws-sdk', '~> 2'
22
23
 
23
24
  spec.add_development_dependency 'bundler', '~> 1.7'
24
25
  spec.add_development_dependency 'rake', '~> 10.0'
25
26
  spec.add_development_dependency 'mocha', '~> 1.1'
27
+ spec.add_development_dependency 'minitest', '~> 5.8'
26
28
 
27
29
  end
data/lib/kindly/db.rb ADDED
@@ -0,0 +1,150 @@
1
+ require 'kindly'
2
+ require 'aws-sdk'
3
+
4
+ module Kindly
5
+ class DB
6
+
7
+ DEFAULTS = {
8
+ :table_names => {
9
+ :data => 'job-data',
10
+ :pending => 'job-pending',
11
+ :running => 'job-running',
12
+ :completed => 'job-completed',
13
+ :failed => 'job-failed'
14
+ }
15
+ }
16
+
17
+ def initialize(options = {})
18
+ @config = DEFAULTS.merge(options)
19
+ @db = Aws::DynamoDB::Client.new(region: 'us-west-2')
20
+ end
21
+
22
+ def user
23
+ @user ||= Aws::IAM::CurrentUser.new(region: 'us-west-2')
24
+ end
25
+
26
+ def insert_job(job_name, input)
27
+ item = {
28
+ 'JobId' => SecureRandom.uuid,
29
+ 'JobName' => job_name,
30
+ 'RequestedAt' => Time.now.to_s,
31
+ 'RequestedBy' => user.user_name
32
+ }
33
+
34
+ unless input.empty?
35
+ data = insert_job_data(input)
36
+ item['InputDataId'] = data['JobDataId']
37
+ end
38
+
39
+ @db.put_item({ table_name: 'job-pending', item: item })
40
+ item
41
+ end
42
+
43
+ def insert_job_data(data)
44
+ item = {
45
+ 'JobDataId' => SecureRandom.uuid,
46
+ 'Data' => data,
47
+ 'CreatedAt' => Time.now.to_s
48
+ }
49
+ @db.put_item({ table_name: 'job-data', item: item })
50
+ item
51
+ end
52
+
53
+ def fetch_job(job_name, job_id)
54
+ job = Registry.find(job_name)
55
+ fields = fetch_job_fields(job_id)
56
+ add_fields_to_job(job, fields)
57
+
58
+ if job.fields.has_key?('InputDataId')
59
+ input = fetch_job_data(job.fields['InputDataId'])
60
+ job.input = input
61
+ end
62
+ job
63
+ end
64
+
65
+ def update_job_status(job, job_status)
66
+ case job_status
67
+ when :running
68
+ delete_job_status(job, :pending)
69
+ when :completed, :failed
70
+ delete_job_status(job, :running)
71
+ else
72
+ raise "#{new_status} is invalid for job #{job.fields['JobId']}."
73
+ end
74
+ insert_job_status(job, job_status)
75
+ end
76
+
77
+ private
78
+
79
+ def fetch_job_fields(job_id)
80
+ response = @db.scan({
81
+ table_name: @config[:table_names][:pending],
82
+ select: 'ALL_ATTRIBUTES',
83
+ filter_expression: "JobId = :job_id",
84
+ expression_attribute_values: { ":job_id": job_id }
85
+ })
86
+
87
+ raise no_jobs(job_id) if response.items.length == 0
88
+ raise too_many_jobs(job_id) if response.items.length > 1
89
+ response.items[0]
90
+ end
91
+
92
+ def fetch_job_data(job_data_id)
93
+ response = @db.scan({
94
+ table_name: @config[:table_names][:data],
95
+ select: 'ALL_ATTRIBUTES',
96
+ filter_expression: "JobDataId = :job_data_id",
97
+ expression_attribute_values: { ":job_data_id": job_data_id }
98
+ })
99
+
100
+ raise no_job_data(job_data_id) if response.items.length == 0
101
+ raise too_many_job_data(job_data_id) if response.items.length > 1
102
+ response.items[0]['Data']
103
+ end
104
+
105
+ def add_fields_to_job(job, fields)
106
+ job.instance_eval do
107
+ def fields
108
+ @fields
109
+ end
110
+
111
+ def fields=(val)
112
+ @fields = val
113
+ end
114
+ end
115
+ job.fields = fields
116
+ end
117
+
118
+ def insert_job_status(job, job_status)
119
+ job.fields['CreatedAt'] = Time.now.to_s
120
+ @db.put_item({
121
+ table_name: @config[:table_names][job_status],
122
+ item: job.fields
123
+ })
124
+ end
125
+
126
+ def delete_job_status(job, job_status)
127
+ @db.delete_item({
128
+ table_name: @config[:table_names][job_status],
129
+ key: { 'JobId': job.fields['JobId'] }
130
+ })
131
+ end
132
+
133
+ def no_jobs(job_id)
134
+ "No pending jobs found for #{job_id}."
135
+ end
136
+
137
+ def too_many_jobs(job_id)
138
+ "Found too many pending job records for #{job_id}."
139
+ end
140
+
141
+ def no_job_data(job_data_id)
142
+ "No job data found for #{job_data_id}."
143
+ end
144
+
145
+ def too_many_job_data(job_data_id)
146
+ "Found too many job data records for #{job_data_id}."
147
+ end
148
+
149
+ end
150
+ end
@@ -0,0 +1,15 @@
1
+ require 'kindly'
2
+
3
+ module Kindly
4
+ module Jobs
5
+ class DoNothing
6
+
7
+ def run
8
+ puts "Nothing happened."
9
+ end
10
+
11
+ end
12
+
13
+ Kindly::Registry.register(:do_nothing, DoNothing.new)
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'kindly'
2
+
3
+ module Kindly
4
+ module Jobs
5
+ class TestJob
6
+
7
+ def run
8
+ puts "fields: #{@fields}"
9
+ end
10
+
11
+ end
12
+
13
+ Kindly::Registry.register(:test_job, TestJob.new)
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require 'kindly'
2
+
3
+ module Kindly
4
+ module Jobs
5
+ class TestJobWithInput
6
+
7
+ attr_accessor :input
8
+
9
+ def run
10
+ puts "input: #{@input}"
11
+ end
12
+
13
+ end
14
+
15
+ Kindly::Registry.register(:test_job_with_input, TestJobWithInput.new)
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'kindly'
2
+
3
+ module Kindly
4
+ module Jobs
5
+ class TestJobWithOutput
6
+
7
+ attr_accessor :output
8
+
9
+ def run
10
+ @output = 'goodbye'
11
+ end
12
+
13
+ end
14
+
15
+ Kindly::Registry.register(:test_job_with_output, TestJobWithOutput.new)
16
+ end
17
+ end
@@ -0,0 +1,56 @@
1
+ require 'kindly'
2
+ require 'aws-sdk'
3
+
4
+ module Kindly
5
+ class Queue
6
+
7
+ def initialize
8
+ @sqs = Aws::SQS::Client.new(region: 'us-west-2')
9
+ end
10
+
11
+ def add(job_name, job_id)
12
+ @sqs.send_message({
13
+ queue_url: queue_url(job_name),
14
+ message_body: "#{@job_name} has been requested.",
15
+ message_attributes: {
16
+ 'JobId' => {
17
+ string_value: job_id,
18
+ data_type: "String",
19
+ },
20
+ },
21
+ })
22
+ end
23
+
24
+ def pop(job_name)
25
+ response = @sqs.receive_message({
26
+ queue_url: queue_url(job_name),
27
+ message_attribute_names: ['JobId'],
28
+ max_number_of_messages: 1
29
+ })
30
+ raise too_many_messages(job_name) if response.messages.length > 1
31
+ return nil if response.messages.length == 0
32
+
33
+ message = response.messages[0]
34
+ job_id = message.message_attributes['JobId'].string_value
35
+
36
+ @sqs.delete_message({
37
+ queue_url: queue_url(job_name),
38
+ receipt_handle: message.receipt_handle
39
+ })
40
+
41
+ job_id
42
+ end
43
+
44
+ private
45
+
46
+ def queue_url(job_name)
47
+ queue = job_name.to_s.gsub('_', '-')
48
+ "https://sqs.us-west-2.amazonaws.com/529271381487/#{queue}"
49
+ end
50
+
51
+ def too_many_messages(job_name)
52
+ "Found too many messages for #{job_name}."
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,30 @@
1
+ require 'kindly'
2
+
3
+ module Kindly
4
+ module Registry
5
+
6
+ def self.register(job_name, job)
7
+ @@jobs ||= {}
8
+ @@jobs[job_name.to_sym] = job
9
+ end
10
+
11
+ def self.unregister(job_name)
12
+ @@jobs.delete(job_name.to_sym)
13
+ end
14
+
15
+ def self.find(job_name)
16
+ raise no_job(job_name) unless registered?(job_name)
17
+ @@jobs[job_name.to_sym]
18
+ end
19
+
20
+ private
21
+
22
+ def self.no_job(job_name)
23
+ "No job registered with name #{job_name}."
24
+ end
25
+
26
+ def self.registered?(job_name)
27
+ @@jobs.has_key?(job_name.to_sym)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ require 'kindly'
2
+
3
+ module Kindly
4
+ class Requester
5
+
6
+ def initialize
7
+ @queue = Queue.new
8
+ @db = DB.new
9
+ end
10
+
11
+ def request(job_name, input = {})
12
+ job = @db.insert_job(job_name, input)
13
+ @queue.add(job_name, job['JobId'])
14
+ end
15
+
16
+ end
17
+ end
data/lib/kindly/runner.rb CHANGED
@@ -3,28 +3,60 @@ require 'kindly'
3
3
  module Kindly
4
4
  class Runner
5
5
 
6
- def initialize(handler)
7
- @handler = handler
6
+ def initialize
7
+ @queue = Queue.new
8
+ @db = DB.new
8
9
  end
9
10
 
10
- def run(migration)
11
- output = capture_output do
11
+ def run(job_name)
12
+ job_id = @queue.pop(job_name)
13
+ if job_id.nil?
14
+ puts "No pending requests for #{job_name}."
15
+ return false
16
+ end
17
+
18
+ job = @db.fetch_job(job_name, job_id)
19
+ run_job(job)
20
+
21
+ job.respond_to?(:output) ? job.output : {}
22
+ end
23
+
24
+ private
25
+
26
+ def run_job(job)
27
+ job.fields['RanBy'] = @db.user.user_name
28
+ job.fields['StartedAt'] = Time.now.to_s
29
+ @db.update_job_status(job, :running)
30
+
31
+ failed = false
32
+ log = capture_stdout do
33
+ puts "#{job.fields['JobId']} started at #{job.fields['StartedAt']}."
12
34
  begin
13
- migration.running!
14
- @handler.run(migration)
15
- migration.completed!
16
- rescue Exception
35
+ job.run
36
+ rescue
37
+ failed = true
17
38
  puts $!, $@
18
- migration.failed!
39
+ end
40
+ job.fields['FinishedAt'] = Time.now.to_s
41
+ puts "#{job.fields['JobId']} finished at #{job.fields['FinishedAt']}."
42
+
43
+ if job.respond_to? :output
44
+ data = @db.insert_job_data(job.output)
45
+ job.fields['OutputDataId'] = data['JobDataId']
19
46
  end
20
47
  end
48
+ job.fields['Log'] = log.split("\n")
21
49
 
22
- write_log_file(migration, output)
50
+ if failed
51
+ @db.update_job_status(job, :failed)
52
+ else
53
+ @db.update_job_status(job, :completed)
54
+ end
23
55
  end
24
56
 
25
57
  private
26
58
 
27
- def capture_output
59
+ def capture_stdout
28
60
  begin
29
61
  old_stdout = $stdout
30
62
  $stdout = StringIO.new('', 'w')
@@ -35,10 +67,5 @@ module Kindly
35
67
  end
36
68
  end
37
69
 
38
- def write_log_file(migration, output)
39
- filename = "#{migration.filename}.log"
40
- File.open(filename, 'w') { |file| file.write(output) }
41
- end
42
-
43
70
  end
44
71
  end
@@ -1,3 +1,3 @@
1
1
  module Kindly
2
- VERSION = '0.0.6'
2
+ VERSION = '0.1.0'
3
3
  end
data/lib/kindly.rb CHANGED
@@ -1,38 +1,23 @@
1
- require 'kindly/migration'
1
+ require 'kindly/db'
2
+ require 'kindly/queue'
3
+ require 'kindly/registry'
4
+ require 'kindly/requester'
2
5
  require 'kindly/runner'
3
- require 'kindly/handlers'
4
- require 'kindly/handlers/do_nothing'
5
6
  require 'kindly/version'
7
+ require 'kindly/jobs/do_nothing'
8
+ require 'kindly/jobs/test_job'
9
+ require 'kindly/jobs/test_job_with_input'
10
+ require 'kindly/jobs/test_job_with_output'
11
+ require 'aws-sdk'
6
12
 
7
13
  module Kindly
8
14
 
9
- def self.run(handler_name, source = '_migrations')
10
- @@source = source
11
- puts "Kindly run #{handler_name} in #{source} directory."
12
-
13
- handler = Handlers.find(handler_name)
14
- runner = Runner.new(handler)
15
- migrations = find_migrations(handler.ext)
16
-
17
- puts "No migrations found for #{handler_name} handler." if migrations.empty?
18
- migrations.each { |migration| runner.run(migration) }
19
- end
20
-
21
- def self.source
22
- @@source
23
- end
24
-
25
- private
26
-
27
- def self.find_migrations(ext)
28
- filenames = Dir[File.join(source, 'pending', "*.#{ext}")]
29
- build_migrations(filenames)
15
+ def self.run(job_name)
16
+ Runner.new.run(job_name)
30
17
  end
31
18
 
32
- def self.build_migrations(filenames)
33
- migrations = []
34
- filenames.each { |filename| migrations << Migration.new(filename) }
35
- migrations
19
+ def self.request(job_name, input = {})
20
+ Requester.new.request(job_name, input)
36
21
  end
37
22
 
38
23
  end
@@ -0,0 +1,15 @@
1
+ require 'kindly'
2
+
3
+ module Fixtures
4
+ module Jobs
5
+ class Fail
6
+
7
+ def run
8
+ raise "This handler fails every time."
9
+ end
10
+
11
+ end
12
+
13
+ Kindly::Registry.register(:fail, Fail.new)
14
+ end
15
+ end
@@ -1,108 +1,114 @@
1
- require 'kindly'
2
- require 'minitest/autorun'
3
- require 'mocha/mini_test'
4
-
5
- describe 'Migration' do
6
-
7
- let(:filename) { File.join('test', 'fixtures', 'pending', 'one.json') }
8
- let(:migration) { migration = Kindly::Migration.new(filename) }
9
-
10
- before(:each) do
11
- Kindly.stubs(:source).returns(File.join('test', 'fixtures'))
12
- end
13
-
14
- describe 'logs' do
15
-
16
- before(:each) { migration.stubs(:move) }
17
-
18
- it 'when running' do
19
- output = capture_output { migration.running! }
20
- assert running?(output)
21
- end
22
-
23
- it 'when completed' do
24
- output = capture_output { migration.completed! }
25
- assert completed?(output)
26
- end
27
-
28
- it 'when failed' do
29
- output = capture_output { migration.failed! }
30
- assert failed?(output)
31
- end
32
-
33
- def running?(output)
34
- output.include?("#{filename} running")
35
- end
36
-
37
- def completed?(output)
38
- output.include?("#{filename} completed") && !failed?(output)
39
- end
40
-
41
- def failed?(output)
42
- output.include?("#{filename} failed") && !completed?(output)
43
- end
44
-
45
- end
46
-
47
- describe 'moves files' do
48
-
49
- let(:source) { File.join('test', 'fixtures') }
50
- let(:tmp_dir) { File.join(source, 'tmp') }
51
-
52
- before(:each) do
53
- FileUtils.mkdir(tmp_dir) unless Dir.exist?(tmp_dir)
54
- Dir[File.join(source, 'pending', '*.json')].each do |file|
55
- FileUtils.cp(file, tmp_dir)
56
- end
57
- end
58
-
59
- after(:each) do
60
- restore_pending
61
- remove(File.join(source, 'running'))
62
- remove(File.join(source, 'completed'))
63
- remove(File.join(source, 'failed'))
64
- remove(tmp_dir)
65
- end
66
-
67
- it 'when running' do
68
- capture_output { migration.running! }
69
- assert File.exist?(File.join(source, 'running', File.basename(filename)))
70
- end
71
-
72
- it 'when completed' do
73
- capture_output { migration.completed! }
74
- assert File.exist?(File.join(source, 'completed', File.basename(filename)))
75
- end
76
-
77
- it 'when failed' do
78
- capture_output { migration.failed! }
79
- assert File.exist?(File.join(source, 'failed', File.basename(filename)))
80
- end
81
-
82
- def restore_pending
83
- pending_dir = File.join(source, 'pending')
84
- FileUtils.rm_r(pending_dir)
85
- FileUtils.mkdir(pending_dir)
86
- Dir[File.join(tmp_dir, '*.json')].each do |file|
87
- FileUtils.cp(file, pending_dir)
88
- end
89
- end
90
-
91
- def remove(dir)
92
- FileUtils.rm_r(dir) if Dir.exist?(dir)
93
- end
94
-
95
- end
96
-
97
- def capture_output
98
- begin
99
- old_stdout = $stdout
100
- $stdout = StringIO.new('', 'w')
101
- yield
102
- $stdout.string
103
- ensure
104
- $stdout = old_stdout
105
- end
106
- end
107
-
108
- end
1
+ # require 'kindly'
2
+ # require 'minitest/autorun'
3
+ # require 'mocha/mini_test'
4
+ #
5
+ # describe 'Job' do
6
+ # let(:source) { File.join('test', 'fixtures', 'jobs', 'read_json') }
7
+ # let(:config) {
8
+ # {
9
+ # :source => source,
10
+ # :pending => File.join(source, 'pending'),
11
+ # :running => File.join(source, 'running'),
12
+ # :completed => File.join(source, 'completed'),
13
+ # :failed => File.join(source, 'failed')
14
+ # }
15
+ # }
16
+ # let(:filename) { File.join(config[:pending], 'one.json') }
17
+ # let(:job) { job = Kindly::Job.new(filename) }
18
+ #
19
+ # before(:each) do
20
+ # Kindly.stubs(:config).returns(config)
21
+ # end
22
+ #
23
+ # describe 'logs' do
24
+ # before(:each) { job.stubs(:move) }
25
+ #
26
+ # it 'when running' do
27
+ # output = capture_output { job.running! }
28
+ # assert running?(output)
29
+ # end
30
+ #
31
+ # it 'when completed' do
32
+ # output = capture_output { job.completed! }
33
+ # assert completed?(output)
34
+ # end
35
+ #
36
+ # it 'when failed' do
37
+ # output = capture_output { job.failed! }
38
+ # assert failed?(output)
39
+ # end
40
+ #
41
+ # def running?(output)
42
+ # output.include?("#{filename} running")
43
+ # end
44
+ #
45
+ # def completed?(output)
46
+ # output.include?("#{filename} completed") && !failed?(output)
47
+ # end
48
+ #
49
+ # def failed?(output)
50
+ # output.include?("#{filename} failed") && !completed?(output)
51
+ # end
52
+ #
53
+ # end
54
+ #
55
+ # describe 'moves files' do
56
+ #
57
+ # let(:tmp_dir) { File.join(source, 'tmp') }
58
+ #
59
+ # before(:each) do
60
+ # FileUtils.mkdir(tmp_dir) unless Dir.exist?(tmp_dir)
61
+ # Dir[File.join(source, 'pending', '*.json')].each do |file|
62
+ # FileUtils.cp(file, tmp_dir)
63
+ # end
64
+ # end
65
+ #
66
+ # after(:each) do
67
+ # restore_pending
68
+ # remove(config[:running])
69
+ # remove(config[:completed])
70
+ # remove(config[:failed])
71
+ # remove(tmp_dir)
72
+ # end
73
+ #
74
+ # it 'when running' do
75
+ # capture_output { job.running! }
76
+ # assert File.exist?(File.join(config[:running], File.basename(filename)))
77
+ # end
78
+ #
79
+ # it 'when completed' do
80
+ # capture_output { job.completed! }
81
+ # assert File.exist?(File.join(config[:completed], File.basename(filename)))
82
+ # end
83
+ #
84
+ # it 'when failed' do
85
+ # capture_output { job.failed! }
86
+ # assert File.exist?(File.join(config[:failed], File.basename(filename)))
87
+ # end
88
+ #
89
+ # def restore_pending
90
+ # FileUtils.rm_r(config[:pending])
91
+ # FileUtils.mkdir(config[:pending])
92
+ # Dir[File.join(tmp_dir, '*.json')].each do |file|
93
+ # FileUtils.cp(file, config[:pending])
94
+ # end
95
+ # end
96
+ #
97
+ # def remove(dir)
98
+ # FileUtils.rm_r(dir) if Dir.exist?(dir)
99
+ # end
100
+ #
101
+ # end
102
+ #
103
+ # def capture_output
104
+ # begin
105
+ # old_stdout = $stdout
106
+ # $stdout = StringIO.new('', 'w')
107
+ # yield
108
+ # $stdout.string
109
+ # ensure
110
+ # $stdout = old_stdout
111
+ # end
112
+ # end
113
+ #
114
+ # end
@@ -0,0 +1,24 @@
1
+ require 'kindly'
2
+ require 'minitest/autorun'
3
+
4
+ describe 'Kindly::Registry' do
5
+
6
+ let(:registry) { Kindly::Registry }
7
+ let(:do_nothing) { Kindly::Jobs::DoNothing.new }
8
+
9
+ it 'throws if job is not registered' do
10
+ assert_raises(RuntimeError) { registry.find(:missing) }
11
+ end
12
+
13
+ it 'allows job to be registered' do
14
+ registry.register :do_nothing, do_nothing
15
+ assert registry.find(:do_nothing) == do_nothing
16
+ end
17
+
18
+ it 'allows job to be unregistered' do
19
+ registry.register :do_nothing, do_nothing
20
+ registry.unregister :do_nothing
21
+ assert_raises(RuntimeError) { registry.find(:do_nothing) }
22
+ end
23
+
24
+ end
@@ -1,44 +1,77 @@
1
1
  require 'kindly'
2
2
  require 'minitest/autorun'
3
3
  require 'mocha/mini_test'
4
- require 'fileutils'
4
+ require 'fixtures/jobs/fail'
5
5
 
6
- describe 'Runner' do
7
6
 
8
- let(:filename) { File.join('test', 'fixtures', 'pending', 'one.json') }
9
- let(:migration) { migration = Kindly::Migration.new(filename) }
10
- let(:runner) { Kindly::Runner.new(Kindly::Handlers::DoNothing.new) }
7
+ describe 'Kindly::Runner' do
11
8
 
12
- before(:each) do
13
- migration.stubs(:move)
14
- end
9
+ # let(:job) { mock() }
10
+ #
11
+ # before(:each) do
12
+ # job.stubs(:fetch)
13
+ # job.stubs(:data)
14
+ # job.stubs(:running!)
15
+ # end
15
16
 
16
- after(:each) do
17
- logfile = "#{filename}.log"
18
- FileUtils.rm(logfile) if File.exist?(logfile)
19
- end
20
-
21
- it 'sets migration to running if loads succeeds' do
22
- migration.expects(:running!).once
23
- runner.run(migration)
24
- end
25
-
26
- it 'sets migration to loading even if load fails' do
27
- migration.stubs(:load).raises
28
- migration.expects(:running!).once
29
- runner.run(migration)
30
- end
31
-
32
- it 'sets migration to completed if Runner succeeds' do
33
- migration.expects(:completed!).once
34
- migration.expects(:failed!).never
35
- runner.run(migration)
36
- end
37
-
38
- it 'writes log file' do
39
- runner.run(migration)
40
- expected_log_file = "#{migration.filename}.log"
41
- assert File.exist?(expected_log_file)
42
- end
17
+ # it 'returns if the job is a success' do
18
+ # job.stubs(:completed!)
19
+ # result = Kindly::Runner.new(:do_nothing).run(job)
20
+ # assert result[:success]
21
+ # end
22
+ #
23
+ # it 'returns if the job is not a success' do
24
+ # job.stubs(:failed!)
25
+ # result = Kindly::Runner.new(:fail).run(job)
26
+ # refute result[:success]
27
+ # end
43
28
 
44
29
  end
30
+
31
+ # require 'kindly'
32
+ # require 'minitest/autorun'
33
+ # require 'mocha/mini_test'
34
+ # require 'fileutils'
35
+ # require 'fixtures/handlers/fail'
36
+ #
37
+ # describe 'Runner' do
38
+ #
39
+ # let(:read_json) { File.join('test', 'fixtures', 'jobs', 'read_json') }
40
+ # let(:filename) { File.join(read_json, 'pending', 'one.json') }
41
+ # let(:job) { job = Kindly::Job.new(filename) }
42
+ # let(:runner) { Kindly::Runner.new(Kindly::Handlers::DoNothing.new) }
43
+ # let(:runner_that_fails) { Kindly::Runner.new(Fixtures::Handlers::Fail.new) }
44
+ #
45
+ # before(:each) do
46
+ # job.stubs(:move)
47
+ # end
48
+ #
49
+ # after(:each) do
50
+ # logfile = "#{filename}.log"
51
+ # FileUtils.rm(logfile) if File.exist?(logfile)
52
+ # end
53
+ #
54
+ # it 'sets job to running' do
55
+ # job.expects(:running!).once
56
+ # runner.run(job)
57
+ # end
58
+ #
59
+ # it 'sets job to completed if job succeeds' do
60
+ # job.expects(:completed!).once
61
+ # job.expects(:failed!).never
62
+ # runner.run(job)
63
+ # end
64
+ #
65
+ # it 'sets job to failed if job fails' do
66
+ # job.expects(:completed!).never
67
+ # job.expects(:failed!).once
68
+ # runner_that_fails.run(job)
69
+ # end
70
+ #
71
+ # it 'writes log file' do
72
+ # runner.run(job)
73
+ # expected_log_file = "#{job.filename}.log"
74
+ # assert File.exist?(expected_log_file)
75
+ # end
76
+ #
77
+ # end
data/test/kindly_test.rb CHANGED
@@ -1,27 +1,60 @@
1
1
  require 'kindly'
2
2
  require 'minitest/autorun'
3
- require 'mocha/mini_test'
3
+ # require 'mocha/mini_test'
4
4
 
5
5
  describe 'Kindly' do
6
6
 
7
- it 'runs given handler name' do
8
- Kindly.stubs(:source).returns(File.join('test', 'fixtures'))
9
- Kindly::Runner.any_instance.expects(:run).twice
10
- capture_output { Kindly.run(:do_nothing) }
11
- end
7
+ # it 'works' do
8
+ # Kindly.request :test_job
9
+ # end
12
10
 
13
- it 'defaults source to _migrations' do
14
- Kindly::Runner.any_instance.stubs(:run)
15
- capture_output { Kindly.run(:do_nothing) }
16
- assert Kindly.source == '_migrations'
17
- end
11
+ # it 'returns true if message was handled' do
12
+ # Kindly::Runner.any_instance.stubs(:run)
13
+ # Kindly::Queue.any_instance.stubs(:pop).returns([1, { hello: 'world' }])
14
+ # Kindly::Queue.any_instance.stubs(:delete)
15
+ # assert Kindly.run(:do_nothing)
16
+ # end
17
+ #
18
+ # it 'returns false if message was not found' do
19
+ # Kindly::Runner.any_instance.stubs(:run)
20
+ # Kindly::Queue.any_instance.stubs(:pop).returns([nil, nil])
21
+ # Kindly::Queue.any_instance.stubs(:delete)
22
+ # capture_output { refute Kindly.run(:do_nothing) }
23
+ # end
18
24
 
19
- it 'allows source to be overridden' do
20
- Kindly::Runner.any_instance.stubs(:run)
21
- fixtures = File.join('test', 'fixtures')
22
- capture_output { Kindly.run(:do_nothing, fixtures) }
23
- assert Kindly.source == fixtures
24
- end
25
+ # let(:read_json) { File.join('test', 'fixtures', 'jobs', 'read_json') }
26
+ # let(:pending) { File.join(read_json, 'pending') }
27
+ #
28
+ # it 'runs given handler name' do
29
+ # Kindly.stubs(:config).returns(:source => read_json)
30
+ # Kindly::Runner.any_instance.expects(:run).twice
31
+ # capture_output { Kindly.run(:do_nothing) }
32
+ # end
33
+ #
34
+ # it 'defaults source to _jobs' do
35
+ # Kindly::Runner.any_instance.stubs(:run)
36
+ # capture_output { Kindly.run(:do_nothing) }
37
+ # assert Kindly.config[:source] == '_jobs'
38
+ # end
39
+ #
40
+ # it 'allows source to be overridden' do
41
+ # Kindly::Runner.any_instance.stubs(:run)
42
+ # capture_output { Kindly.run(:do_nothing, :source => read_json) }
43
+ # assert Kindly.config[:source] == read_json
44
+ # end
45
+ #
46
+ # it 'defaults pending to _jobs/pending' do
47
+ # expected = File.join('_jobs', 'pending')
48
+ # Kindly::Runner.any_instance.stubs(:run)
49
+ # capture_output { Kindly.run(:do_nothing) }
50
+ # assert Kindly.config[:pending] == expected
51
+ # end
52
+ #
53
+ # it 'allows pending to be overridden' do
54
+ # Kindly::Runner.any_instance.stubs(:run)
55
+ # capture_output { Kindly.run(:do_nothing, :pending => pending) }
56
+ # assert_equal pending, Kindly.config[:pending]
57
+ # end
25
58
 
26
59
  def capture_output
27
60
  begin
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kindly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Scott
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-26 00:00:00.000000000 Z
11
+ date: 2016-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mercenary
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -66,11 +80,24 @@ dependencies:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
82
  version: '1.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5.8'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '5.8'
69
97
  description:
70
98
  email:
71
99
  - i@gregoryjscott.com
72
- executables:
73
- - kindly
100
+ executables: []
74
101
  extensions: []
75
102
  extra_rdoc_files: []
76
103
  files:
@@ -79,18 +106,21 @@ files:
79
106
  - LICENSE
80
107
  - README.md
81
108
  - Rakefile
82
- - bin/kindly
83
109
  - kindly.gemspec
84
110
  - lib/kindly.rb
85
- - lib/kindly/handlers.rb
86
- - lib/kindly/handlers/do_nothing.rb
87
- - lib/kindly/migration.rb
111
+ - lib/kindly/db.rb
112
+ - lib/kindly/jobs/do_nothing.rb
113
+ - lib/kindly/jobs/test_job.rb
114
+ - lib/kindly/jobs/test_job_with_input.rb
115
+ - lib/kindly/jobs/test_job_with_output.rb
116
+ - lib/kindly/queue.rb
117
+ - lib/kindly/registry.rb
118
+ - lib/kindly/requester.rb
88
119
  - lib/kindly/runner.rb
89
120
  - lib/kindly/version.rb
90
- - test/fixtures/pending/one.json
91
- - test/fixtures/pending/two.json
92
- - test/kindly/handlers_test.rb
121
+ - test/fixtures/jobs/fail.rb
93
122
  - test/kindly/migration_test.rb
123
+ - test/kindly/registry_test.rb
94
124
  - test/kindly/runner_test.rb
95
125
  - test/kindly_test.rb
96
126
  homepage: https://github.com/gregoryjscott/kindly
@@ -113,14 +143,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
143
  version: '0'
114
144
  requirements: []
115
145
  rubyforge_project:
116
- rubygems_version: 2.2.2
146
+ rubygems_version: 2.4.5
117
147
  signing_key:
118
148
  specification_version: 4
119
- summary: Kindly run migrations of any kind.
149
+ summary: Kindly run jobs of any kind.
120
150
  test_files:
121
- - test/fixtures/pending/one.json
122
- - test/fixtures/pending/two.json
123
- - test/kindly/handlers_test.rb
151
+ - test/fixtures/jobs/fail.rb
124
152
  - test/kindly/migration_test.rb
153
+ - test/kindly/registry_test.rb
125
154
  - test/kindly/runner_test.rb
126
155
  - test/kindly_test.rb
data/bin/kindly DELETED
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib })
4
-
5
- require 'kindly'
6
- require 'mercenary'
7
-
8
- Mercenary.program(:kindly) do |p|
9
- p.version Kindly::VERSION
10
- p.description 'Kindly run migrations of any kind.'
11
- p.syntax 'kindly <handler> [options]'
12
-
13
- p.option 'source', '--source DIR', 'Host directory of the kindly directory structure.'
14
- p.action do |args, options|
15
- if args.empty?
16
- puts p
17
- elsif options['source']
18
- Kindly.run(args.first.to_sym, options['source'])
19
- else
20
- Kindly.run(args.first.to_sym)
21
- end
22
- end
23
- end
@@ -1,19 +0,0 @@
1
- require 'kindly'
2
-
3
- module Kindly
4
- module Handlers
5
- class DoNothing
6
-
7
- def ext
8
- '*'
9
- end
10
-
11
- def run(migration)
12
- puts "The handler for #{migration.filename} did nothing."
13
- end
14
-
15
- end
16
-
17
- register(:do_nothing, DoNothing.new)
18
- end
19
- end
@@ -1,29 +0,0 @@
1
- require 'kindly'
2
-
3
- module Kindly
4
- module Handlers
5
-
6
- def self.register(name, handler)
7
- @@handlers ||= {}
8
- @@handlers[name.to_sym] = handler
9
- end
10
-
11
- def self.unregister(name)
12
- @@handlers.delete(name.to_sym)
13
- end
14
-
15
- def self.find(name)
16
- if not_registered(name)
17
- raise "No handler registered with name #{name.to_sym}."
18
- end
19
-
20
- @@handlers[name.to_sym]
21
- end
22
-
23
- private
24
-
25
- def self.not_registered(name)
26
- !@@handlers.has_key?(name.to_sym)
27
- end
28
- end
29
- end
@@ -1,37 +0,0 @@
1
- require 'kindly'
2
- require 'fileutils'
3
- require 'json'
4
-
5
- module Kindly
6
- class Migration
7
-
8
- attr_reader :filename
9
-
10
- def initialize(filename)
11
- @filename = filename
12
- end
13
-
14
- def move(destination)
15
- path = File.join(Kindly.source, destination)
16
- FileUtils.mkdir(path) unless Dir.exist?(path)
17
- FileUtils.mv(@filename, path)
18
- @filename = File.join(path, File.basename(@filename))
19
- end
20
-
21
- def running!
22
- move('running')
23
- puts "#{@filename} running."
24
- end
25
-
26
- def completed!
27
- move('completed')
28
- puts "#{@filename} completed."
29
- end
30
-
31
- def failed!
32
- move('failed')
33
- puts "#{@filename} failed."
34
- end
35
-
36
- end
37
- end
@@ -1,3 +0,0 @@
1
- {
2
- "one": 1
3
- }
@@ -1,3 +0,0 @@
1
- {
2
- "two": 2
3
- }
@@ -1,24 +0,0 @@
1
- require 'kindly'
2
- require 'minitest/autorun'
3
-
4
- describe 'Kindly::Handlers' do
5
-
6
- let(:handlers) { Kindly::Handlers }
7
- let(:handler) { Kindly::Handlers::DoNothing.new }
8
-
9
- it 'throws if handler is not registered' do
10
- assert_raises(RuntimeError) { handlers.find(:missing) }
11
- end
12
-
13
- it 'allows handlers to be registered' do
14
- handlers.register :different, handler
15
- assert handlers.find(:different) == handler
16
- end
17
-
18
- it 'allows handlers to be unregistered' do
19
- handlers.register :different, handler
20
- handlers.unregister :different
21
- assert_raises(RuntimeError) { handlers.find(:different) }
22
- end
23
-
24
- end