simple_pipeline 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +94 -31
- data/lib/simple_pipeline.rb +29 -31
- data/lib/simple_pipeline/timeout.rb +22 -11
- data/lib/simple_pipeline/version.rb +1 -1
- data/spec/simple_pipeline_spec.rb +50 -48
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4919357b1935895facfb4607f74def1253c1dea
|
4
|
+
data.tar.gz: 5dace42d21950ae0f05c21d39d338d09f58d0d2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51a6fe55e765bd7d78114cc8d3d77aa7eaac165105292e79e57f64f6d80367b7de3173e25591244b4aa9412d0c38ffc88e24926446a2865d037f4efff2bc6f9e
|
7
|
+
data.tar.gz: 6fa5f5a13a1834194fda4cbef8701c80be10817c648d3f97c1d6a5d51417f5b35e247a3d2f6f9a5c54ee1d59085574302976ef19049e75418fa20a9c8572046b
|
data/README.md
CHANGED
@@ -1,31 +1,94 @@
|
|
1
|
-
# SimplePipeline
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
## Installation
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
```
|
10
|
-
gem
|
11
|
-
```
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
## Usage
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
1
|
+
# SimplePipeline
|
2
|
+
|
3
|
+
**SimplePipeline** is a simple framework for sequentially executing a series of code components. Each code component takes a payload, modifies it, and moves it down the pipe for the next component and so forth. One of the design goals is to make it as flexible as possible, yet keep it simple.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install the gem from RubyGems:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
gem install simple_pipeline
|
11
|
+
```
|
12
|
+
|
13
|
+
If you use Bundler, just add it to your Gemfile and run `bundle install`
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'simple_pipeline'
|
17
|
+
```
|
18
|
+
|
19
|
+
I have only tested this gem on Ruby 2.3.0, but there shouldn't be any reason why it wouldn't work on earlier Ruby versions as well.
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
pipeline = SimplePipeline.new
|
25
|
+
|
26
|
+
pipeline.add Pipe1.new
|
27
|
+
pipeline.add Pipe2.new
|
28
|
+
pipeline.add Pipe3.new
|
29
|
+
|
30
|
+
payload = {:some_key => some_value}
|
31
|
+
|
32
|
+
pipeline.process payload
|
33
|
+
```
|
34
|
+
|
35
|
+
**SimplePipeline** will call the ```process``` method on each of the pipes in the order that they were added to the pipeline.
|
36
|
+
|
37
|
+
## Pipes
|
38
|
+
|
39
|
+
A **pipe** can be any Ruby object that has a ```process``` method that accepts a single argument (the payload object). For example:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
class Pipe1
|
43
|
+
def process (payload)
|
44
|
+
# Do something with the payload object
|
45
|
+
end
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
## Payload
|
50
|
+
|
51
|
+
The **payload** can be an Array, Hash, or any other Ruby object. Individual pipes have the responsibility to know what to do with the payload that is passed into the ```process``` method.
|
52
|
+
|
53
|
+
## Timeout
|
54
|
+
|
55
|
+
You can use the **SimplePipeline::Timeout** mixin to enforce a timeout value (in seconds) for a pipe. If the execution of the ```process``` method exceeds the specified timeout value, a ```Timeout::Error``` will be thrown.
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
class TimeoutPipe
|
59
|
+
include SimplePipeline::Timeout
|
60
|
+
|
61
|
+
set_timeout 3 # Set the timeout value to be three seconds
|
62
|
+
|
63
|
+
def process (payload)
|
64
|
+
# Do something
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
pipeline = SimplePipeline.new
|
69
|
+
pipeline.add TimeoutPipe.new
|
70
|
+
|
71
|
+
payload = {:some_key => some_value}
|
72
|
+
|
73
|
+
# Will throw a Timeout::Error if execution of process on the TimeoutPipe instance takes longer than 3 seconds
|
74
|
+
pipeline.process payload
|
75
|
+
```
|
76
|
+
|
77
|
+
You can also set the timeout value on a per instance basis.
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
pipeline = SimplePipeline.new
|
81
|
+
|
82
|
+
pipe1 = TimeoutPipe.new
|
83
|
+
pipe1.set_timeout 10
|
84
|
+
|
85
|
+
pipe2 = TimeoutPipe.new
|
86
|
+
pipe2.set_timeout 60
|
87
|
+
|
88
|
+
pipeline.add pipe1
|
89
|
+
pipeline.add pipe2
|
90
|
+
```
|
91
|
+
This will override the timeout value set by the class definition.
|
92
|
+
|
93
|
+
## License
|
94
|
+
**SimplePipeline** is released under the [MIT license](MIT-LICENSE).
|
data/lib/simple_pipeline.rb
CHANGED
@@ -3,35 +3,33 @@ require "simple_pipeline/version"
|
|
3
3
|
|
4
4
|
|
5
5
|
class SimplePipeline
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
alias :length :size
|
36
|
-
|
6
|
+
def initialize
|
7
|
+
@pipes = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add (pipe)
|
11
|
+
begin
|
12
|
+
raise ArgumentError, "invalid pipe - incorrect number of arguments for process() method (should be 1)" unless pipe.class.instance_method(:process).arity == 1
|
13
|
+
rescue NameError
|
14
|
+
raise ArgumentError, "invalid pipe - process() method not found"
|
15
|
+
end
|
16
|
+
|
17
|
+
@pipes << pipe
|
18
|
+
end
|
19
|
+
|
20
|
+
def size
|
21
|
+
return @pipes.size
|
22
|
+
end
|
23
|
+
|
24
|
+
def process (payload)
|
25
|
+
@pipes.each do |pipe|
|
26
|
+
if pipe.is_a? SimplePipeline::Timeout
|
27
|
+
pipe.process_with_timeout(payload)
|
28
|
+
else
|
29
|
+
pipe.process(payload)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :length :size
|
37
35
|
end
|
@@ -1,19 +1,30 @@
|
|
1
1
|
require 'timeout'
|
2
2
|
|
3
3
|
class SimplePipeline
|
4
|
+
module Timeout
|
5
|
+
def self.included (base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
base.class_variable_set(:@@timeout_in_sec, 0)
|
8
|
+
end
|
4
9
|
|
5
|
-
|
10
|
+
module ClassMethods
|
11
|
+
def set_timeout (sec)
|
12
|
+
self.class_variable_set(:@@timeout_in_sec, sec)
|
13
|
+
end
|
14
|
+
end
|
6
15
|
|
7
|
-
|
8
|
-
|
9
|
-
|
16
|
+
def timeout=(sec)
|
17
|
+
@timeout_in_sec = sec
|
18
|
+
end
|
10
19
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
20
|
+
def process_with_timeout (payload)
|
21
|
+
::Timeout::timeout(timeout) {
|
22
|
+
process(payload)
|
23
|
+
}
|
24
|
+
end
|
18
25
|
|
26
|
+
def timeout
|
27
|
+
@timeout_in_sec || self.class.class_variable_get(:@@timeout_in_sec)
|
28
|
+
end
|
29
|
+
end
|
19
30
|
end
|
@@ -1,63 +1,65 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
class TestPipe
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
def process (payload)
|
5
|
+
payload[:test_value] *= 10
|
6
|
+
end
|
7
7
|
end
|
8
8
|
|
9
9
|
class BadPipe
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
def process (payload1, payload2)
|
11
|
+
# do nothing
|
12
|
+
end
|
13
13
|
end
|
14
14
|
|
15
15
|
class TimeoutPipe
|
16
|
-
|
16
|
+
include SimplePipeline::Timeout
|
17
17
|
|
18
|
-
|
19
|
-
set_timeout 1 # seconds
|
20
|
-
end
|
18
|
+
set_timeout 3 # seconds
|
21
19
|
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
def process (payload)
|
21
|
+
sleep 10 # seconds
|
22
|
+
end
|
25
23
|
end
|
26
24
|
|
27
25
|
describe SimplePipeline do
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
26
|
+
it "should support three normal pipes" do
|
27
|
+
pipeline = SimplePipeline.new
|
28
|
+
pipeline.add TestPipe.new
|
29
|
+
pipeline.add TestPipe.new
|
30
|
+
pipeline.add TestPipe.new
|
31
|
+
|
32
|
+
payload = {:test_value => 10}
|
33
|
+
|
34
|
+
pipeline.process(payload)
|
35
|
+
|
36
|
+
expect(pipeline.size).to eq 3
|
37
|
+
expect(payload[:test_value]).to eq 10000
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should throw an error for invalid pipes" do
|
41
|
+
pipeline = SimplePipeline.new
|
42
|
+
|
43
|
+
expect {
|
44
|
+
pipeline.add Object.new # not a pipe
|
45
|
+
}.to raise_error(ArgumentError)
|
46
|
+
|
47
|
+
expect {
|
48
|
+
pipeline.add BadPipe
|
49
|
+
}.to raise_error(ArgumentError)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should support pipes with timeout" do
|
53
|
+
pipeline = SimplePipeline.new
|
54
|
+
pipe = TimeoutPipe.new
|
55
|
+
pipeline.add pipe
|
56
|
+
|
57
|
+
expect(pipe.timeout).to eq 3
|
58
|
+
pipe.timeout = 1
|
59
|
+
expect(pipe.timeout).to eq 1
|
60
|
+
|
61
|
+
expect {
|
62
|
+
pipeline.process({})
|
63
|
+
}.to raise_error(Timeout::Error)
|
64
|
+
end
|
63
65
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_pipeline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Wong
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-07-
|
11
|
+
date: 2016-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|