kindly 0.0.6 → 0.1.0

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.
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