forklift_etl 1.0.19 → 1.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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OTg3Mzg3YTI0MDg0YTMyMDZiNWZjYWNiNTllNmYwZWZjMGYzZTQxOA==
4
+ YjE2NGE4ZGQ0N2M3YWI2OTE4MDdkMGIzYTdhZTUzOWRmNzM0YzU3MQ==
5
5
  data.tar.gz: !binary |-
6
- YzI1NWNkZWE0MzRlMTQ2NDQ5ZDc0MGYxMTUyYWQ1ZWRmMGRkYmEzYQ==
6
+ N2EzZTBmNDFhZjEyMTQ3MzZkNmZkMDU3NmU3NGY1MzUyYmY2YmU1MQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MzI0NWNhOWFiNjViODEzNDQzOWRjNTFhZmUwMDdhYWIyMzIxNzE2MWM5ZDdm
10
- ZTJlMTBjMjY1MjY4NDUzNjg5YjAxNGI4ODQ3MDYzMjNjOWU2NjFjN2Y1NzFi
11
- NDBjYmUzODA0YmNlNmY4OTk3YWIzMmNhNzcwYmM3ZjUwYzFkM2Q=
9
+ NTQyNzc0OGI0YzMyOGQyNzE4YmQ3MDBlMDEwMDk2ZjQ4ODFlMTI1MmU2M2Mx
10
+ MzJjZDg2NzA1Y2Y1NDVmOWU0NTAzNDhkNmRhMGFjNGY2ZmE0MGYyYzJmNzBh
11
+ MGU5NmE3NmYyMTE2MzRjMTc2MzIwZjYwZTE3MWViOTE5ZmRlMDc=
12
12
  data.tar.gz: !binary |-
13
- MjM1NWZkZWI2MDJhYmNmZmQ2ZGJhZDk3Y2M3YzNmODBhYjhjY2JiNzU3MTgy
14
- ZThmM2Y5OWExNjZjYjU0YWNiYWZhZDdhYWE3YjE1MDgzODhkM2MxODk4ZWI0
15
- OTA4ZGEzOWI4ZDdmMTdlNjA4OGIzZDQ2YmVkYzY1NzFjOWM5ZjY=
13
+ N2EwNjZiM2JlNzQzOTFlNGUzM2I5YWEwM2Y0ZGRlMjUyZTZhZTlkZWQ3MTJh
14
+ NzA3YTE5ZDgzMTkxMzFjZjZiMWYyYzMzZTEzZjVlMDg0NTlhYWUyNDBlODJm
15
+ Njk2ZGJmOTIwOTgyOWFkNTRkMTFkYjZhMjFkZDMzODZhOGJhOWQ=
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- forklift_etl (1.0.19)
4
+ forklift_etl (1.1.0)
5
5
  activesupport (~> 4.0, >= 4.0.0)
6
6
  elasticsearch (~> 1.0, >= 1.0.0)
7
7
  lumberjack (~> 1.0, >= 1.0.0)
data/lib/forklift/plan.rb CHANGED
@@ -37,17 +37,25 @@ module Forklift
37
37
  logger.debug "loaded a #{type.camelcase} connection from #{f}"
38
38
  rescue Exception => e
39
39
  logger.fatal "cannot create a class type of #{loader} from #{f} | #{e}"
40
- raise e
40
+ # raise e ## Don't raise here, but let a step fail so the error_handler can report
41
41
  end
42
42
  end
43
43
  end
44
44
 
45
+
46
+ def default_error_handler
47
+ return lambda {|name, e| raise e }
48
+ end
49
+
45
50
  def step(*args, &block)
46
- name = args[0].to_sym
51
+ name = args[0].to_sym
52
+ error_handler = default_error_handler
53
+ error_handler = args[1] unless args[1].nil?
47
54
  self.steps[name] = {
48
- :ran => false,
49
- :to_run => false,
50
- :block => block
55
+ :ran => false,
56
+ :to_run => false,
57
+ :block => block,
58
+ :error_handler => error_handler,
51
59
  }
52
60
  end
53
61
 
@@ -63,8 +71,12 @@ module Forklift
63
71
  self.logger.log "skipping step `#{name}`"
64
72
  else
65
73
  self.logger.log "*** step: #{name} ***"
66
- step[:block].call
67
- step[:ran] = true
74
+ begin
75
+ step[:block].call
76
+ step[:ran] = true
77
+ rescue Exception => e
78
+ step[:error_handler].call(name, e)
79
+ end
68
80
  end
69
81
  end
70
82
  end
@@ -1,3 +1,3 @@
1
1
  module Forklift
2
- VERSION = "1.0.19"
2
+ VERSION = "1.1.0"
3
3
  end
data/readme.md CHANGED
@@ -265,6 +265,29 @@ end
265
265
 
266
266
  When you use steps, you can run your whole plan, or just part if it with command line arguments. For example, `forklift plan.rb "Elasticsearch Import"` would just run that single portion of the plan. Note that any parts of your plan not within a step will be run each time.
267
267
 
268
+ ### Error Handling
269
+
270
+ By default, exceptions within your plan will raise and crash your application. However, you can pass an optional `error_handler` lambda to your step about how to handle the error. the `error_handler` will be passed (`step_name`,`exception`). If you don't re-raise within your error handler, your plan will continue to excecute. For example:
271
+
272
+ ```ruby
273
+
274
+ error_handler = lambda { |name, exception|
275
+ if exception.class =~ /connection/
276
+ # I can't connect, I should halt
277
+ raise e
278
+ elsif exception.class =~ /SoftError/
279
+ # this type of error is OK
280
+ else
281
+ raise e
282
+ end
283
+ }
284
+
285
+ plan.step('a_complex_step', error_handler){
286
+ # ...
287
+ }
288
+
289
+ ```
290
+
268
291
  ## Transports
269
292
 
270
293
  Transports are how you interact with your data. Every transport defines `read` and `write` methods which handle arrays of data objects (and the helper methods required).
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'misc forklift core' do
4
+ describe 'error handling' do
5
+
6
+ it "un-caught errors will raise" do
7
+ plan = SpecPlan.new
8
+ expect{
9
+ plan.do! {
10
+ plan.step("step_a"){ raise 'BREAK' }
11
+ }
12
+ }.to raise_error 'BREAK'
13
+ plan.pid.delete!
14
+ end
15
+
16
+ it 'can make error handlers' do
17
+ plan = SpecPlan.new
18
+ name = ''
19
+ ex = ''
20
+ error_handler = lambda{ |n, e|
21
+ ex = e
22
+ name = n
23
+ }
24
+ plan.do! {
25
+ plan.step("step_a", error_handler){ raise 'BREAK' }
26
+ }
27
+
28
+ expect(name).to eql :step_a
29
+ expect(ex.to_s).to eql 'BREAK'
30
+ end
31
+
32
+ end
33
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forklift_etl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.19
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Tahler
@@ -179,6 +179,7 @@ files:
179
179
  - spec/template/spec_email_template.erb
180
180
  - spec/unit/connection/mysql_spec.rb
181
181
  - spec/unit/misc/email_spec.rb
182
+ - spec/unit/misc/error_spec.rb
182
183
  - spec/unit/misc/pid_spec.rb
183
184
  - spec/unit/misc/step_spec.rb
184
185
  - template/destination.yml
@@ -237,6 +238,7 @@ test_files:
237
238
  - spec/template/spec_email_template.erb
238
239
  - spec/unit/connection/mysql_spec.rb
239
240
  - spec/unit/misc/email_spec.rb
241
+ - spec/unit/misc/error_spec.rb
240
242
  - spec/unit/misc/pid_spec.rb
241
243
  - spec/unit/misc/step_spec.rb
242
244
  has_rdoc: