transflow 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +50 -0
- data/lib/transflow.rb +17 -69
- data/lib/transflow/flow_dsl.rb +45 -0
- data/lib/transflow/publisher.rb +26 -0
- data/lib/transflow/step_dsl.rb +41 -0
- data/lib/transflow/transaction.rb +42 -0
- data/lib/transflow/version.rb +1 -1
- data/transflow.gemspec +1 -0
- metadata +19 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3dde7fc2cfdb940553b3a4ddabe1004d01ca49a6
|
4
|
+
data.tar.gz: 2c7b0e6c01338cd5087ac5dc332e9c5936d3a5b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4601d2a9a7a8dfd1d72c03199f696483fa1de7bf66f0e398cecd17115bbf6a54333c32c11740ec2998d7626bbb8dadc3aab9088b4ed580f0a71cd2bd0af803d
|
7
|
+
data.tar.gz: f0ccebb883cc983ace244989008a23c649e2b234ced17692923747c95d6be1b185a4528d5e64202fdf71e829b94f5162ffb3e08611eb05286556a4865b1e5b47
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
# 0.0.2 2015-08-16
|
2
|
+
|
3
|
+
## Added
|
4
|
+
|
5
|
+
- Ability to publish events from operations via `publish: true` option (solnic)
|
6
|
+
- Ability to subscribe to events via `Transflow::Transaction#subscribe` interface (solnic)
|
7
|
+
|
8
|
+
[Compare v0.0.1...v0.0.2](https://github.com/rom-rb/rom/compare/v0.0.1...v0.0.2)
|
9
|
+
|
1
10
|
# 0.0.1 2015-08-16
|
2
11
|
|
3
12
|
First public release \o/
|
data/README.md
CHANGED
@@ -51,6 +51,56 @@ errors from multiple steps without stopping the processing. It's not implemented
|
|
51
51
|
yet but *probably* using pub/sub for that will do the work as we can register an
|
52
52
|
error listener that can simply gather errors and return it as a result.
|
53
53
|
|
54
|
+
## Synopsis
|
55
|
+
|
56
|
+
``` ruby
|
57
|
+
DB = []
|
58
|
+
|
59
|
+
container = {
|
60
|
+
validate: -> input { raise "name nil" if input[:name].nil? },
|
61
|
+
persist: -> input { DB << input[:name] }
|
62
|
+
}
|
63
|
+
|
64
|
+
my_business_flow = Transflow(container: container) do
|
65
|
+
step(:validate) { step(:persist) }
|
66
|
+
end
|
67
|
+
|
68
|
+
my_business_flow[{ name: 'Jane' }]
|
69
|
+
|
70
|
+
puts DB.inspect
|
71
|
+
# ["Jane"]
|
72
|
+
|
73
|
+
## The same but with events
|
74
|
+
|
75
|
+
NOTIFICATIONS = []
|
76
|
+
|
77
|
+
class Notify
|
78
|
+
def persist_success(user)
|
79
|
+
NOTIFICATIONS << "#{user} persisted"
|
80
|
+
end
|
81
|
+
|
82
|
+
def persist_failure(user, err)
|
83
|
+
# do sth about that
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
my_business_flow = Transflow(container: container) do
|
88
|
+
step(:validate) { step(:persist, publish: true) }
|
89
|
+
end
|
90
|
+
|
91
|
+
notify = Notify.new
|
92
|
+
|
93
|
+
my_business_flow.subscribe(persist: notify)
|
94
|
+
|
95
|
+
my_business_flow[{ name: 'Jane' }]
|
96
|
+
|
97
|
+
puts DB.inspect
|
98
|
+
# ["Jane"]
|
99
|
+
|
100
|
+
puts NOTIFICATIONS.inspect
|
101
|
+
# ["Jane persisted"]
|
102
|
+
```
|
103
|
+
|
54
104
|
## Installation
|
55
105
|
|
56
106
|
Add this line to your application's Gemfile:
|
data/lib/transflow.rb
CHANGED
@@ -1,73 +1,21 @@
|
|
1
|
-
require 'transproc'
|
2
1
|
require 'transflow/version'
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
class StepDSL
|
22
|
-
attr_reader :name
|
23
|
-
|
24
|
-
attr_reader :handler
|
25
|
-
|
26
|
-
attr_reader :container
|
27
|
-
|
28
|
-
attr_reader :steps
|
29
|
-
|
30
|
-
def initialize(name, options, container, steps, &block)
|
31
|
-
@name = name
|
32
|
-
@handler = options.fetch(:with)
|
33
|
-
@container = container
|
34
|
-
@steps = steps
|
35
|
-
instance_exec(&block) if block
|
36
|
-
end
|
37
|
-
|
38
|
-
def step(*args, &block)
|
39
|
-
self.class.new(*args, container, steps, &block).call
|
40
|
-
end
|
41
|
-
|
42
|
-
def call
|
43
|
-
steps[name] = container[handler]
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
class FlowDSL
|
48
|
-
attr_reader :options
|
49
|
-
|
50
|
-
attr_reader :container
|
51
|
-
|
52
|
-
attr_reader :steps
|
53
|
-
|
54
|
-
def initialize(options, &block)
|
55
|
-
@options = options
|
56
|
-
@container = options.fetch(:container)
|
57
|
-
@steps = {}
|
58
|
-
instance_exec(&block)
|
59
|
-
end
|
60
|
-
|
61
|
-
def step(*args, &block)
|
62
|
-
StepDSL.new(*args, container, steps, &block).call
|
63
|
-
end
|
64
|
-
|
65
|
-
def call
|
66
|
-
Transaction.new(steps, steps.values.reverse.reduce(:>>))
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
2
|
+
require 'transflow/flow_dsl'
|
3
|
+
|
4
|
+
# Define a transaction flow
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
#
|
8
|
+
# container = { do_one: some_obj, do_two: some_obj }
|
9
|
+
#
|
10
|
+
# my_business_flow = Transflow(container: container) do
|
11
|
+
# step(:one, with: :do_one) { step(:two, with: :do_two }
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# my_business_flow[some_input]
|
15
|
+
#
|
16
|
+
# @options [Hash] options The option hash
|
17
|
+
#
|
18
|
+
# @api public
|
71
19
|
def Transflow(options = {}, &block)
|
72
20
|
Transflow::FlowDSL.new(options, &block).call
|
73
21
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'transproc'
|
2
|
+
|
3
|
+
require 'transflow/step_dsl'
|
4
|
+
require 'transflow/transaction'
|
5
|
+
|
6
|
+
module Transflow
|
7
|
+
class FlowDSL
|
8
|
+
module Registry
|
9
|
+
extend Transproc::Registry
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.[](op)
|
13
|
+
if op.respond_to?(:>>)
|
14
|
+
op
|
15
|
+
else
|
16
|
+
Registry[op]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :options
|
21
|
+
|
22
|
+
attr_reader :container
|
23
|
+
|
24
|
+
attr_reader :steps
|
25
|
+
|
26
|
+
def initialize(options, &block)
|
27
|
+
@options = options
|
28
|
+
@container = options.fetch(:container)
|
29
|
+
@steps = {}
|
30
|
+
instance_exec(&block)
|
31
|
+
end
|
32
|
+
|
33
|
+
def step(*args, &block)
|
34
|
+
StepDSL.new(*args, container, steps, &block).call
|
35
|
+
end
|
36
|
+
|
37
|
+
def call
|
38
|
+
Transaction.new(steps, operations.reduce(:>>))
|
39
|
+
end
|
40
|
+
|
41
|
+
def operations
|
42
|
+
steps.values.reverse.map { |op| self.class[op] }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'wisper'
|
2
|
+
|
3
|
+
module Transflow
|
4
|
+
class Publisher
|
5
|
+
include Wisper::Publisher
|
6
|
+
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
attr_reader :op
|
10
|
+
|
11
|
+
def initialize(name, op)
|
12
|
+
@name = name
|
13
|
+
@op = op
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(*args)
|
17
|
+
result = op.call(*args)
|
18
|
+
broadcast(:"#{name}_success", result)
|
19
|
+
result
|
20
|
+
rescue => err
|
21
|
+
broadcast(:"#{name}_failure", *args, err)
|
22
|
+
raise err
|
23
|
+
end
|
24
|
+
alias_method :[], :call
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'transflow/publisher'
|
2
|
+
|
3
|
+
module Transflow
|
4
|
+
class StepDSL
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
attr_reader :handler
|
8
|
+
|
9
|
+
attr_reader :container
|
10
|
+
|
11
|
+
attr_reader :steps
|
12
|
+
|
13
|
+
attr_reader :publish
|
14
|
+
|
15
|
+
def initialize(name, options, container, steps, &block)
|
16
|
+
@name = name
|
17
|
+
@handler = options.fetch(:with)
|
18
|
+
@publish = options.fetch(:publish, false)
|
19
|
+
@container = container
|
20
|
+
@steps = steps
|
21
|
+
instance_exec(&block) if block
|
22
|
+
end
|
23
|
+
|
24
|
+
def step(*args, &block)
|
25
|
+
self.class.new(*args, container, steps, &block).call
|
26
|
+
end
|
27
|
+
|
28
|
+
def call
|
29
|
+
operation = container[handler]
|
30
|
+
|
31
|
+
step =
|
32
|
+
if publish
|
33
|
+
Publisher.new(name, operation)
|
34
|
+
else
|
35
|
+
operation
|
36
|
+
end
|
37
|
+
|
38
|
+
steps[name] = step
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Transflow
|
2
|
+
class TransactionFailedError < StandardError
|
3
|
+
attr_reader :transaction
|
4
|
+
|
5
|
+
attr_reader :original_error
|
6
|
+
|
7
|
+
def initialize(transaction, original_error)
|
8
|
+
@transaction = transaction
|
9
|
+
@original_error = original_error
|
10
|
+
|
11
|
+
super("#{transaction} failed")
|
12
|
+
|
13
|
+
set_backtrace(original_error.backtrace)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Transaction
|
18
|
+
attr_reader :handler
|
19
|
+
|
20
|
+
attr_reader :steps
|
21
|
+
|
22
|
+
def initialize(steps, handler)
|
23
|
+
@steps = steps
|
24
|
+
@handler = handler
|
25
|
+
end
|
26
|
+
|
27
|
+
def subscribe(listeners)
|
28
|
+
listeners.each { |step, listener| steps[step].subscribe(listener) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(*args)
|
32
|
+
handler.call(*args)
|
33
|
+
rescue Transproc::MalformedInputError => err
|
34
|
+
raise TransactionFailedError.new(self, err)
|
35
|
+
end
|
36
|
+
alias_method :[], :call
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
"Transaction(#{steps.keys.join(' => ')})"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/transflow/version.rb
CHANGED
data/transflow.gemspec
CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_runtime_dependency 'transproc', '~> 0.3', '>= 0.3.1'
|
22
|
+
spec.add_runtime_dependency 'wisper'
|
22
23
|
|
23
24
|
spec.add_development_dependency "bundler", "~> 1.10"
|
24
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: transflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
@@ -30,6 +30,20 @@ dependencies:
|
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 0.3.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: wisper
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
33
47
|
- !ruby/object:Gem::Dependency
|
34
48
|
name: bundler
|
35
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -90,6 +104,10 @@ files:
|
|
90
104
|
- bin/console
|
91
105
|
- bin/setup
|
92
106
|
- lib/transflow.rb
|
107
|
+
- lib/transflow/flow_dsl.rb
|
108
|
+
- lib/transflow/publisher.rb
|
109
|
+
- lib/transflow/step_dsl.rb
|
110
|
+
- lib/transflow/transaction.rb
|
93
111
|
- lib/transflow/version.rb
|
94
112
|
- transflow.gemspec
|
95
113
|
homepage: https://github.com/solnic/transflow
|