exel 0.9.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +17 -0
  3. data/.rubocop_todo.yml +43 -0
  4. data/Guardfile +18 -11
  5. data/README.md +3 -0
  6. data/Rakefile +0 -1
  7. data/exel.gemspec +6 -5
  8. data/lib/exel/ast_node.rb +2 -2
  9. data/lib/exel/context.rb +16 -19
  10. data/lib/exel/deferred_context_value.rb +2 -2
  11. data/lib/exel/instruction.rb +2 -2
  12. data/lib/exel/job.rb +5 -5
  13. data/lib/exel/logging.rb +3 -3
  14. data/lib/exel/null_instruction.rb +1 -1
  15. data/lib/exel/processor_helper.rb +3 -5
  16. data/lib/exel/processors/async_processor.rb +3 -3
  17. data/lib/exel/providers/local_file_provider.rb +18 -0
  18. data/lib/exel/providers/threaded_async_provider.rb +13 -0
  19. data/lib/exel/{resource.rb → value.rb} +7 -11
  20. data/lib/exel/version.rb +1 -1
  21. data/lib/exel.rb +10 -1
  22. data/spec/exel/ast_node_spec.rb +3 -15
  23. data/spec/exel/context_spec.rb +40 -22
  24. data/spec/exel/job_spec.rb +8 -8
  25. data/spec/exel/logging_spec.rb +3 -3
  26. data/spec/exel/processors/async_processor_spec.rb +12 -4
  27. data/spec/exel/processors/split_processor_spec.rb +67 -67
  28. data/spec/exel/providers/local_async_provider_spec.rb +19 -0
  29. data/spec/exel/providers/local_file_provider_spec.rb +36 -0
  30. data/spec/exel/sequence_node_spec.rb +6 -13
  31. data/spec/exel/value_spec.rb +51 -0
  32. data/spec/exel_spec.rb +41 -0
  33. data/spec/spec_helper.rb +22 -3
  34. metadata +69 -40
  35. data/lib/exel/execution_worker.rb +0 -13
  36. data/lib/exel/handlers/s3_handler.rb +0 -43
  37. data/lib/exel/handlers/sidekiq_handler.rb +0 -21
  38. data/spec/exel/execution_worker_spec.rb +0 -13
  39. data/spec/exel/handlers/s3_handler_spec.rb +0 -49
  40. data/spec/exel/handlers/sidekiq_handler_spec.rb +0 -54
  41. data/spec/exel/resource_spec.rb +0 -51
metadata CHANGED
@@ -1,115 +1,115 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - yroo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-22 00:00:00.000000000 Z
11
+ date: 2015-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: aws-sdk
14
+ name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2'
20
- type: :runtime
19
+ version: '1.6'
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2'
26
+ version: '1.6'
27
27
  - !ruby/object:Gem::Dependency
28
- name: sidekiq
28
+ name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '3'
34
- type: :runtime
33
+ version: '10'
34
+ type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '3'
40
+ version: '10'
41
41
  - !ruby/object:Gem::Dependency
42
- name: bundler
42
+ name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.6'
47
+ version: '3'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.6'
54
+ version: '3'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rake
56
+ name: guard
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10'
61
+ version: '2'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10'
68
+ version: '2'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rspec
70
+ name: guard-rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '3'
75
+ version: '4'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '3'
82
+ version: '4'
83
83
  - !ruby/object:Gem::Dependency
84
- name: guard
84
+ name: guard-rubocop
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '2'
89
+ version: '1'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '2'
96
+ version: '1'
97
97
  - !ruby/object:Gem::Dependency
98
- name: guard-rspec
98
+ name: terminal-notifier
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '4'
103
+ version: '1'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '4'
110
+ version: '1'
111
111
  - !ruby/object:Gem::Dependency
112
- name: terminal-notifier
112
+ name: terminal-notifier-guard
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
@@ -123,7 +123,21 @@ dependencies:
123
123
  - !ruby/object:Gem::Version
124
124
  version: '1'
125
125
  - !ruby/object:Gem::Dependency
126
- name: terminal-notifier-guard
126
+ name: rubocop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop-rspec
127
141
  requirement: !ruby/object:Gem::Requirement
128
142
  requirements:
129
143
  - - "~>"
@@ -136,6 +150,20 @@ dependencies:
136
150
  - - "~>"
137
151
  - !ruby/object:Gem::Version
138
152
  version: '1'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-rspec-focused
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
139
167
  description: A DSL for defining jobs that can be run in a highly scalable manner
140
168
  email:
141
169
  - dev@yroo.com
@@ -145,6 +173,8 @@ extra_rdoc_files: []
145
173
  files:
146
174
  - ".gitignore"
147
175
  - ".rspec"
176
+ - ".rubocop.yml"
177
+ - ".rubocop_todo.yml"
148
178
  - Gemfile
149
179
  - Guardfile
150
180
  - LICENSE.txt
@@ -156,9 +186,6 @@ files:
156
186
  - lib/exel/context.rb
157
187
  - lib/exel/deferred_context_value.rb
158
188
  - lib/exel/error/job_termination.rb
159
- - lib/exel/execution_worker.rb
160
- - lib/exel/handlers/s3_handler.rb
161
- - lib/exel/handlers/sidekiq_handler.rb
162
189
  - lib/exel/instruction.rb
163
190
  - lib/exel/instruction_node.rb
164
191
  - lib/exel/job.rb
@@ -167,15 +194,14 @@ files:
167
194
  - lib/exel/processor_helper.rb
168
195
  - lib/exel/processors/async_processor.rb
169
196
  - lib/exel/processors/split_processor.rb
170
- - lib/exel/resource.rb
197
+ - lib/exel/providers/local_file_provider.rb
198
+ - lib/exel/providers/threaded_async_provider.rb
171
199
  - lib/exel/sequence_node.rb
200
+ - lib/exel/value.rb
172
201
  - lib/exel/version.rb
173
202
  - spec/exel/ast_node_spec.rb
174
203
  - spec/exel/context_spec.rb
175
204
  - spec/exel/deferred_context_value_spec.rb
176
- - spec/exel/execution_worker_spec.rb
177
- - spec/exel/handlers/s3_handler_spec.rb
178
- - spec/exel/handlers/sidekiq_handler_spec.rb
179
205
  - spec/exel/instruction_node_spec.rb
180
206
  - spec/exel/instruction_spec.rb
181
207
  - spec/exel/job_spec.rb
@@ -183,8 +209,11 @@ files:
183
209
  - spec/exel/null_instruction_spec.rb
184
210
  - spec/exel/processors/async_processor_spec.rb
185
211
  - spec/exel/processors/split_processor_spec.rb
186
- - spec/exel/resource_spec.rb
212
+ - spec/exel/providers/local_async_provider_spec.rb
213
+ - spec/exel/providers/local_file_provider_spec.rb
187
214
  - spec/exel/sequence_node_spec.rb
215
+ - spec/exel/value_spec.rb
216
+ - spec/exel_spec.rb
188
217
  - spec/spec_helper.rb
189
218
  homepage: https://github.com/47colborne/exel
190
219
  licenses:
@@ -206,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
206
235
  version: '0'
207
236
  requirements: []
208
237
  rubyforge_project:
209
- rubygems_version: 2.4.5.1
238
+ rubygems_version: 2.2.2
210
239
  signing_key:
211
240
  specification_version: 4
212
241
  summary: EXEL, the Elastic eXEcution Language
@@ -214,9 +243,6 @@ test_files:
214
243
  - spec/exel/ast_node_spec.rb
215
244
  - spec/exel/context_spec.rb
216
245
  - spec/exel/deferred_context_value_spec.rb
217
- - spec/exel/execution_worker_spec.rb
218
- - spec/exel/handlers/s3_handler_spec.rb
219
- - spec/exel/handlers/sidekiq_handler_spec.rb
220
246
  - spec/exel/instruction_node_spec.rb
221
247
  - spec/exel/instruction_spec.rb
222
248
  - spec/exel/job_spec.rb
@@ -224,6 +250,9 @@ test_files:
224
250
  - spec/exel/null_instruction_spec.rb
225
251
  - spec/exel/processors/async_processor_spec.rb
226
252
  - spec/exel/processors/split_processor_spec.rb
227
- - spec/exel/resource_spec.rb
253
+ - spec/exel/providers/local_async_provider_spec.rb
254
+ - spec/exel/providers/local_file_provider_spec.rb
228
255
  - spec/exel/sequence_node_spec.rb
256
+ - spec/exel/value_spec.rb
257
+ - spec/exel_spec.rb
229
258
  - spec/spec_helper.rb
@@ -1,13 +0,0 @@
1
- require 'sidekiq'
2
-
3
- module EXEL
4
- class ExecutionWorker
5
- include Sidekiq::Worker
6
-
7
- def perform(context_uri)
8
- context = Context.deserialize(context_uri)
9
- block = context[:_block]
10
- block.start(context)
11
- end
12
- end
13
- end
@@ -1,43 +0,0 @@
1
- require 'aws-sdk-resources'
2
- require 'tempfile'
3
-
4
- module EXEL
5
- module Handlers
6
- class S3Handler
7
- def upload(file)
8
- filename = get_filename(file)
9
- obj = get_object(filename)
10
- obj.upload_file(file)
11
- file.close
12
-
13
- "s3://#{filename}"
14
- end
15
-
16
- def download(uri)
17
- filename = uri.partition('://').last
18
- obj = get_object(filename)
19
- file = Tempfile.new(filename, encoding: Encoding::ASCII_8BIT)
20
- obj.get(response_target: file)
21
- file.set_encoding(Encoding::UTF_8)
22
- file
23
- end
24
-
25
- def get_object(filename)
26
- s3 = Aws::S3::Resource.new(
27
- credentials: Aws::Credentials.new(
28
- EXEL.configuration[:aws][:access_key_id],
29
- EXEL.configuration[:aws][:secret_access_key]
30
- ),
31
- region: 'us-east-1'
32
- )
33
- s3.bucket(EXEL.configuration[:s3_bucket]).object(filename)
34
- end
35
-
36
- private
37
-
38
- def get_filename(file)
39
- file.path.split('/').last
40
- end
41
- end
42
- end
43
- end
@@ -1,21 +0,0 @@
1
- require 'sidekiq'
2
-
3
- module EXEL
4
- module Handlers
5
- class SidekiqHandler
6
- def initialize(context)
7
- @context = context
8
- end
9
-
10
- def do_async(block)
11
- @context[:_block] = block
12
-
13
- push_args = {'class' => ExecutionWorker, 'args' => [@context.serialize]}
14
- push_args['queue'] = @context[:queue] if @context[:queue]
15
- push_args['retry'] = @context[:retry] if @context[:retry]
16
-
17
- Sidekiq::Client.push(push_args)
18
- end
19
- end
20
- end
21
- end
@@ -1,13 +0,0 @@
1
- module EXEL
2
- describe ExecutionWorker do
3
- it 'should run the given block with the deserialized context' do
4
- dsl_block = instance_double(SequenceNode)
5
- context = Context.new(test1: 'foo', test2: 2, _block: dsl_block)
6
- context_uri = 'test uri'
7
-
8
- expect(Context).to receive(:deserialize).with(context_uri).and_return(context)
9
- expect(dsl_block).to receive(:start).with(context)
10
- ExecutionWorker.new.perform(context_uri)
11
- end
12
- end
13
- end
@@ -1,49 +0,0 @@
1
- module EXEL
2
- module Handlers
3
- describe S3Handler do
4
- subject(:handler) { S3Handler.new }
5
-
6
- describe '#get_object' do
7
- before do
8
- EXEL.configure { |config| config[:s3_bucket] = 'bucket' }
9
- end
10
-
11
- it 'should have the correct bucket and file names' do
12
- file_name = 'abc.txt'
13
- s3_obj = handler.get_object(file_name)
14
- expect(s3_obj.bucket_name).to eq('bucket')
15
- expect(s3_obj.key).to eq(file_name)
16
- end
17
- end
18
-
19
- describe '#upload' do
20
- let(:file) { double(path: '/path/to/abc.txt', close: nil) }
21
-
22
- it 'should upload a file to s3' do
23
- expect_any_instance_of(Aws::S3::Object).to receive(:upload_file).with(file)
24
-
25
- handler.upload(file)
26
- end
27
-
28
- it 'should return the file URI of the uploaded file' do
29
- allow_any_instance_of(Aws::S3::Object).to receive(:upload_file).with(file)
30
- expect(handler.upload(file)).to eq('s3://abc.txt')
31
- end
32
- end
33
-
34
- describe '#download' do
35
- it 'should download the file from s3' do
36
- file = double(:file)
37
- s3_object = double(:s3_object)
38
-
39
- expect(handler).to receive(:get_object).with('abc.txt').and_return(s3_object)
40
- expect(Tempfile).to receive(:new).with('abc.txt', encoding: Encoding::ASCII_8BIT).and_return(file)
41
- expect(s3_object).to receive(:get).with(hash_including(response_target: file)).and_return(file)
42
- expect(file).to receive(:set_encoding).with(Encoding::UTF_8)
43
-
44
- expect(handler.download('s3://abc.txt')).to eq(file)
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,54 +0,0 @@
1
- module EXEL
2
- module Handlers
3
- describe SidekiqHandler do
4
- subject(:handler) { SidekiqHandler.new(context) }
5
- let(:callback) { instance_double(SequenceNode) }
6
- let(:context) { EXEL::Context.new }
7
- let(:serialized_context_uri) { 'context_uri' }
8
-
9
- describe '#do_async' do
10
- before do
11
- allow(context).to receive(:serialize).and_return(serialized_context_uri)
12
- end
13
-
14
- it 'should add the callback to the context before serializing it' do
15
- expect(context).to receive(:[]=).with(:_block, callback).ordered
16
- expect(context).to receive(:serialize).ordered
17
- handler.do_async(callback)
18
- end
19
-
20
- context 'with queue name' do
21
- let(:context) { EXEL::Context.new(queue: 'import_processor') }
22
-
23
- it 'should push the execution worker to the given queue' do
24
- expect(Sidekiq::Client).to receive(:push).with('queue' => context[:queue], 'class' => ExecutionWorker, 'args' => [serialized_context_uri])
25
- handler.do_async(callback)
26
- end
27
- end
28
-
29
- context 'without queue name' do
30
- it 'should push the execution worker to the default queue' do
31
- expect(Sidekiq::Client).to receive(:push).with('class' => ExecutionWorker, 'args' => [serialized_context_uri])
32
- handler.do_async(callback)
33
- end
34
- end
35
-
36
- context 'with retries specified' do
37
- let(:context) { EXEL::Context.new(retry: 1) }
38
-
39
- it 'should push the execution worker with a specified number of retries' do
40
- expect(Sidekiq::Client).to receive(:push).with('retry' => context[:retry], 'class' => ExecutionWorker, 'args' => [serialized_context_uri])
41
- handler.do_async(callback)
42
- end
43
- end
44
-
45
- context 'with no retries specified' do
46
- it 'should push the execution worker with no specified number of retries' do
47
- expect(Sidekiq::Client).to receive(:push).with('class' => ExecutionWorker, 'args' => [serialized_context_uri])
48
- handler.do_async(callback)
49
- end
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -1,51 +0,0 @@
1
- module EXEL
2
- describe Resource do
3
- let(:s3_uri) { 's3://test_file.csv' }
4
-
5
- describe '.remotize' do
6
- context 'when passed in value is not a file' do
7
- it 'should return the value' do
8
- expect(Resource.remotize('test string')).to eq('test string')
9
- end
10
- end
11
-
12
- context 'when the passed in value is a file' do
13
- [File, Tempfile].each do |file_class|
14
- context "with a #{file_class}" do
15
- before do
16
- @file = instance_double(file_class)
17
- allow(@file).to receive(:is_a?) { |klass| klass == file_class }
18
- end
19
-
20
- it 'should upload the file to S3' do
21
- expect_any_instance_of(Handlers::S3Handler).to receive(:upload).with(@file)
22
- Resource.remotize(@file)
23
- end
24
-
25
- it 'should return a remote file URI' do
26
- allow_any_instance_of(Handlers::S3Handler).to receive(:upload).with(@file).and_return(s3_uri)
27
- expect(Resource.remotize(@file)).to eq(s3_uri)
28
- end
29
- end
30
- end
31
- end
32
- end
33
-
34
- describe '.localize' do
35
- context 'with a localized value' do
36
- it 'should return the value' do
37
- expect(Resource.localize('test string')).to eq('test string')
38
- end
39
- end
40
-
41
- context 'with a remote file' do
42
- it 'should return the downloaded file' do
43
- file = double(:file)
44
- expect_any_instance_of(Handlers::S3Handler).to receive(:download).with(s3_uri).and_return(file)
45
-
46
- expect(Resource.localize(s3_uri)).to eq(file)
47
- end
48
- end
49
- end
50
- end
51
- end