setl 0.0.3 → 0.0.4
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 +4 -4
- data/lib/setl/delegates.rb +43 -0
- data/lib/setl/errors.rb +25 -0
- data/lib/setl/etl.rb +12 -15
- data/lib/setl/version.rb +1 -1
- data/spec/error_handling_spec.rb +57 -7
- data/spec/etl_spec.rb +2 -2
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a89bb7b59c0609b79d8cf15d6028ec1f737beae
|
4
|
+
data.tar.gz: cc162c0522666a70fbf9180592e4b0d3e5d128aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15e2d85fef8add097abbda5890201332de3fc251f73e4e61b7c15cb74dcc5f09c64352e039db1411cab8506fe91142157079bebcc96233aed039270a73e70244
|
7
|
+
data.tar.gz: 4c57e706725c5f33b6b5d820bb444590c0508b0b78a2bf47cf8ad9b6d1d6715fdd763e06f42da3a5f040a042d2b4511e4ad6a20c4dab0fd38c49da246e037a1a
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative 'errors'
|
2
|
+
|
3
|
+
module Setl
|
4
|
+
class Delegator
|
5
|
+
def initialize(item, error_handler)
|
6
|
+
@item = item
|
7
|
+
@error_handler = error_handler
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
attr_reader :item, :error_handler
|
13
|
+
end
|
14
|
+
|
15
|
+
class Source < Delegator
|
16
|
+
def each(&block)
|
17
|
+
item.each(&block)
|
18
|
+
rescue StandardError => e
|
19
|
+
# Allow our errors to go through
|
20
|
+
if e.is_a? ETLError
|
21
|
+
raise e
|
22
|
+
else
|
23
|
+
error_handler.(SourceError.new("Failed to read from source"))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Transform < Delegator
|
29
|
+
def call(row, &block)
|
30
|
+
item.call(row, &block)
|
31
|
+
rescue StandardError => e
|
32
|
+
error_handler.(ProcessingError.new(row, "Failed to process #{row}"))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Destination < Delegator
|
37
|
+
def call(row, &block)
|
38
|
+
item.call(row, &block)
|
39
|
+
rescue StandardError => e
|
40
|
+
error_handler.(DestinationError.new(row, "Failed to send #{row}"))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/setl/errors.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Setl
|
2
|
+
class ETLError < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class ProcessingError < ETLError
|
6
|
+
def initialize(row, message=nil)
|
7
|
+
super message
|
8
|
+
@row = row
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :row
|
12
|
+
end
|
13
|
+
|
14
|
+
class SourceError < ETLError
|
15
|
+
end
|
16
|
+
|
17
|
+
class DestinationError < ETLError
|
18
|
+
def initialize(row, message=nil)
|
19
|
+
super message
|
20
|
+
@row = row
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :row
|
24
|
+
end
|
25
|
+
end
|
data/lib/setl/etl.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
+
require_relative 'delegates'
|
2
|
+
|
1
3
|
module Setl
|
2
4
|
class ETL
|
3
|
-
def initialize(source, destination, stop_on_errors: false, error_handler: nil)
|
4
|
-
@source = source
|
5
|
-
@destination = destination
|
5
|
+
def initialize(source, destination, transform, stop_on_errors: false, error_handler: nil)
|
6
6
|
@stop_on_errors = stop_on_errors
|
7
7
|
@error_handler = error_handler || DefaultHandler.new(stop_on_errors)
|
8
|
+
|
9
|
+
@source = Source.new(source, @error_handler)
|
10
|
+
@destination = Destination.new(destination, @error_handler)
|
11
|
+
@transform = Transform.new(transform, @error_handler)
|
8
12
|
end
|
9
13
|
|
10
|
-
def process
|
14
|
+
def process
|
11
15
|
source.each do |row|
|
12
16
|
@last_row = row
|
13
17
|
|
14
|
-
|
15
|
-
destination.(transform.(row))
|
16
|
-
rescue StandardError => e
|
17
|
-
error_handler.(row, e)
|
18
|
-
end
|
18
|
+
destination.(transform.(row))
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -23,10 +23,7 @@ module Setl
|
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
|
-
attr_reader :source, :destination, :stop_on_errors, :error_handler
|
27
|
-
end
|
28
|
-
|
29
|
-
class ProcessingError < StandardError
|
26
|
+
attr_reader :source, :destination, :transform, :stop_on_errors, :error_handler
|
30
27
|
end
|
31
28
|
|
32
29
|
class DefaultHandler
|
@@ -34,8 +31,8 @@ module Setl
|
|
34
31
|
@reraise = reraise
|
35
32
|
end
|
36
33
|
|
37
|
-
def call(
|
38
|
-
raise
|
34
|
+
def call(exception)
|
35
|
+
raise exception if reraise?
|
39
36
|
end
|
40
37
|
|
41
38
|
private
|
data/lib/setl/version.rb
CHANGED
data/spec/error_handling_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'setl/etl'
|
|
3
3
|
|
4
4
|
module Setl
|
5
5
|
RSpec.describe 'error handling' do
|
6
|
-
let(:etl) { ETL.new(source, destination) }
|
6
|
+
let(:etl) { ETL.new(source, destination, transform) }
|
7
7
|
let(:source) { [1, 2] }
|
8
8
|
let(:destination) { double('Destination', call: true) }
|
9
9
|
let(:transform) do
|
@@ -14,7 +14,7 @@ module Setl
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
let(:process) { etl.process
|
17
|
+
let(:process) { etl.process }
|
18
18
|
|
19
19
|
context 'by default' do
|
20
20
|
it 'rescues the error' do
|
@@ -29,7 +29,7 @@ module Setl
|
|
29
29
|
end
|
30
30
|
|
31
31
|
context 'when configured to stop on errors' do
|
32
|
-
let(:etl) { ETL.new(source, destination, stop_on_errors: true) }
|
32
|
+
let(:etl) { ETL.new(source, destination, transform, stop_on_errors: true) }
|
33
33
|
|
34
34
|
it 'stops processing when a processing error occurs' do
|
35
35
|
expect { process }.to raise_error(ProcessingError, 'Failed to process 1')
|
@@ -45,14 +45,64 @@ module Setl
|
|
45
45
|
end
|
46
46
|
|
47
47
|
context 'when provided an error handler' do
|
48
|
-
let(:handler)
|
49
|
-
|
48
|
+
let(:handler) do
|
49
|
+
Class.new do
|
50
|
+
def self.call(exception)
|
51
|
+
raise exception
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
50
55
|
|
51
|
-
|
52
|
-
|
56
|
+
let(:etl) { ETL.new(source, destination, transform, error_handler: handler) }
|
57
|
+
|
58
|
+
it 'sends a processing error to the handler' do
|
59
|
+
expect(handler).to receive(:call).with(an_instance_of(ProcessingError))
|
53
60
|
|
54
61
|
process
|
55
62
|
end
|
63
|
+
|
64
|
+
specify 'the error contains the original cause' do
|
65
|
+
begin
|
66
|
+
process
|
67
|
+
rescue ProcessingError => e
|
68
|
+
expect(e.cause).to be_a RuntimeError
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when the source raises an exception' do
|
73
|
+
let(:handler) { double('ErrorHandler', call: true) }
|
74
|
+
|
75
|
+
let(:source) do
|
76
|
+
Class.new do
|
77
|
+
def self.each
|
78
|
+
raise "nope"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'sends a SourceError to the handler' do
|
84
|
+
expect(handler).to receive(:call).with(an_instance_of(SourceError))
|
85
|
+
|
86
|
+
process
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'when the destination raises an exception' do
|
91
|
+
let(:handler) { double('ErrorHandler', call: true) }
|
92
|
+
let(:destination) do
|
93
|
+
Class.new do
|
94
|
+
def self.call(row)
|
95
|
+
raise "lol"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'sends a destination error to the handler' do
|
101
|
+
expect(handler).to receive(:call).with(an_instance_of(DestinationError))
|
102
|
+
|
103
|
+
process
|
104
|
+
end
|
105
|
+
end
|
56
106
|
end
|
57
107
|
end
|
58
108
|
end
|
data/spec/etl_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'setl/etl'
|
|
3
3
|
|
4
4
|
module Setl
|
5
5
|
RSpec.describe 'etl' do
|
6
|
-
let(:etl) { ETL.new(source, destination) }
|
6
|
+
let(:etl) { ETL.new(source, destination, transform) }
|
7
7
|
|
8
8
|
describe 'processing a row' do
|
9
9
|
let(:row) { 'hello' }
|
@@ -13,7 +13,7 @@ module Setl
|
|
13
13
|
let(:transform) { double('Transform', call: processed_data) }
|
14
14
|
|
15
15
|
before do
|
16
|
-
etl.process
|
16
|
+
etl.process
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'delegates the processing to the transform' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: setl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leonard Garvey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -70,6 +70,8 @@ files:
|
|
70
70
|
- bin/rspec
|
71
71
|
- lib/setl.rb
|
72
72
|
- lib/setl/controller.rb
|
73
|
+
- lib/setl/delegates.rb
|
74
|
+
- lib/setl/errors.rb
|
73
75
|
- lib/setl/etl.rb
|
74
76
|
- lib/setl/version.rb
|
75
77
|
- setl.gemspec
|
@@ -97,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
99
|
version: '0'
|
98
100
|
requirements: []
|
99
101
|
rubyforge_project:
|
100
|
-
rubygems_version: 2.
|
102
|
+
rubygems_version: 2.2.2
|
101
103
|
signing_key:
|
102
104
|
specification_version: 4
|
103
105
|
summary: Simple Extract Transform & Load - setl
|
@@ -106,3 +108,4 @@ test_files:
|
|
106
108
|
- spec/error_handling_spec.rb
|
107
109
|
- spec/etl_spec.rb
|
108
110
|
- spec/spec_helper.rb
|
111
|
+
has_rdoc:
|