exel 0.9.0 → 1.0.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.
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