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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6c18bc0bd37bd89215142adefd13b8a965ea0994
4
- data.tar.gz: 7827d58aeef106f8cf0eb6969381b76433f44a4e
3
+ metadata.gz: 3dde7fc2cfdb940553b3a4ddabe1004d01ca49a6
4
+ data.tar.gz: 2c7b0e6c01338cd5087ac5dc332e9c5936d3a5b5
5
5
  SHA512:
6
- metadata.gz: 531682614e131a47544798c2700fd2c22258b6fa9a61c309515ef5a6bf72404dbd8a4faa29e8111c3f3c930d73243e7791546d1b4d6ff0aaa1699b0755a0833d
7
- data.tar.gz: e87f9e64c7249a0c550e43b148391da884bdd90bb23b0eeb3131249961c8fd4882a9e6f0d43a7b98e3fb7513c7d699cf63fa63138df53a184f3dbdfa61621643
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
- module Transflow
5
- class Transaction
6
- attr_reader :handler
7
-
8
- attr_reader :steps
9
-
10
- def initialize(steps, handler)
11
- @steps = steps
12
- @handler = handler
13
- end
14
-
15
- def call(*args)
16
- handler.call(*args)
17
- end
18
- alias_method :[], :call
19
- end
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
@@ -1,3 +1,3 @@
1
1
  module Transflow
2
- VERSION = '0.0.1'.freeze
2
+ VERSION = '0.0.2'.freeze
3
3
  end
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.1
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