standard-procedure-plumbing 0.3.3 → 0.4.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 +4 -4
- data/README.md +58 -88
- data/lib/plumbing/actor/async.rb +38 -0
- data/lib/plumbing/actor/inline.rb +22 -0
- data/lib/plumbing/actor/kernel.rb +9 -0
- data/lib/plumbing/{valve → actor}/rails.rb +1 -1
- data/lib/plumbing/{valve → actor}/threaded.rb +22 -27
- data/lib/plumbing/actor/transporter.rb +61 -0
- data/lib/plumbing/actor.rb +63 -0
- data/lib/plumbing/config.rb +8 -8
- data/lib/plumbing/pipe.rb +2 -3
- data/lib/plumbing/version.rb +1 -1
- data/lib/plumbing.rb +1 -1
- data/spec/examples/{valve_spec.rb → actor_spec.rb} +14 -14
- data/spec/examples/pipe_spec.rb +4 -4
- data/spec/plumbing/a_pipe.rb +11 -9
- data/spec/plumbing/actor/transporter_spec.rb +158 -0
- data/spec/plumbing/actor_spec.rb +208 -0
- metadata +27 -11
- data/lib/plumbing/valve/async.rb +0 -43
- data/lib/plumbing/valve/inline.rb +0 -20
- data/lib/plumbing/valve/message.rb +0 -5
- data/lib/plumbing/valve.rb +0 -71
- data/spec/plumbing/valve_spec.rb +0 -171
@@ -1,20 +1,21 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
RSpec.shared_examples "an example
|
3
|
+
RSpec.shared_examples "an example actor" do |runs_in_background|
|
4
4
|
it "queries an object" do
|
5
5
|
@person = Employee.start "Alice"
|
6
6
|
|
7
|
-
expect(@person.name).to eq "Alice"
|
8
|
-
expect(@person.job_title).to eq "Sales assistant"
|
7
|
+
expect(await { @person.name }).to eq "Alice"
|
8
|
+
expect(await { @person.job_title }).to eq "Sales assistant"
|
9
9
|
|
10
10
|
@time = Time.now
|
11
11
|
# `greet_slowly` is a query so will block until a response is received
|
12
|
-
expect(@person.greet_slowly).to eq "H E L L O"
|
12
|
+
expect(await { @person.greet_slowly }).to eq "H E L L O"
|
13
13
|
expect(Time.now - @time).to be > 0.1
|
14
14
|
|
15
15
|
@time = Time.now
|
16
|
-
# we're
|
17
|
-
|
16
|
+
# we're not awaiting the result, so this should run in the background (unless we're using inline mode)
|
17
|
+
@person.greet_slowly
|
18
|
+
|
18
19
|
expect(Time.now - @time).to be < 0.1 if runs_in_background
|
19
20
|
expect(Time.now - @time).to be > 0.1 if !runs_in_background
|
20
21
|
end
|
@@ -22,17 +23,16 @@ RSpec.shared_examples "an example valve" do |runs_in_background|
|
|
22
23
|
it "commands an object" do
|
23
24
|
@person = Employee.start "Alice"
|
24
25
|
@person.promote
|
25
|
-
@job_title = @person.job_title
|
26
|
+
@job_title = await { @person.job_title }
|
26
27
|
expect(@job_title).to eq "Sales manager"
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
30
|
-
RSpec.describe "
|
31
|
+
RSpec.describe "Actor example: " do
|
31
32
|
# standard:disable Lint/ConstantDefinitionInBlock
|
32
33
|
class Employee
|
33
|
-
include Plumbing::
|
34
|
-
|
35
|
-
command :promote
|
34
|
+
include Plumbing::Actor
|
35
|
+
async :name, :job_title, :greet_slowly, :promote
|
36
36
|
|
37
37
|
def initialize(name)
|
38
38
|
@name = name
|
@@ -58,7 +58,7 @@ RSpec.describe "Valve example: " do
|
|
58
58
|
Plumbing.configure mode: :inline, &example
|
59
59
|
end
|
60
60
|
|
61
|
-
it_behaves_like "an example
|
61
|
+
it_behaves_like "an example actor", false
|
62
62
|
end
|
63
63
|
|
64
64
|
context "async mode" do
|
@@ -68,7 +68,7 @@ RSpec.describe "Valve example: " do
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
-
it_behaves_like "an example
|
71
|
+
it_behaves_like "an example actor", true
|
72
72
|
end
|
73
73
|
|
74
74
|
context "threaded mode" do
|
@@ -76,6 +76,6 @@ RSpec.describe "Valve example: " do
|
|
76
76
|
Plumbing.configure mode: :threaded, &example
|
77
77
|
end
|
78
78
|
|
79
|
-
it_behaves_like "an example
|
79
|
+
it_behaves_like "an example actor", true
|
80
80
|
end
|
81
81
|
end
|
data/spec/examples/pipe_spec.rb
CHANGED
@@ -6,7 +6,7 @@ RSpec.describe "Pipe examples" do
|
|
6
6
|
@source = Plumbing::Pipe.start
|
7
7
|
|
8
8
|
@result = []
|
9
|
-
@
|
9
|
+
@source.add_observer do |event|
|
10
10
|
@result << event.type
|
11
11
|
end
|
12
12
|
|
@@ -22,7 +22,7 @@ RSpec.describe "Pipe examples" do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
@result = []
|
25
|
-
@
|
25
|
+
@filter.add_observer do |event|
|
26
26
|
@result << event.type
|
27
27
|
end
|
28
28
|
|
@@ -55,7 +55,7 @@ RSpec.describe "Pipe examples" do
|
|
55
55
|
@filter = EveryThirdEvent.new(source: @source)
|
56
56
|
|
57
57
|
@result = []
|
58
|
-
@
|
58
|
+
@filter.add_observer do |event|
|
59
59
|
@result << event.type
|
60
60
|
end
|
61
61
|
|
@@ -73,7 +73,7 @@ RSpec.describe "Pipe examples" do
|
|
73
73
|
@junction = Plumbing::Junction.start @first_source, @second_source
|
74
74
|
|
75
75
|
@result = []
|
76
|
-
@
|
76
|
+
@junction.add_observer do |event|
|
77
77
|
@result << event.type
|
78
78
|
end
|
79
79
|
|
data/spec/plumbing/a_pipe.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
RSpec.shared_examples "a pipe" do
|
2
2
|
it "adds a block observer" do
|
3
3
|
@pipe = described_class.start
|
4
|
-
@observer =
|
5
|
-
|
4
|
+
@observer = await do
|
5
|
+
@pipe.add_observer do |event|
|
6
|
+
puts event.type
|
7
|
+
end
|
6
8
|
end
|
7
|
-
expect(@pipe.is_observer?(@observer)).to eq true
|
9
|
+
expect(await { @pipe.is_observer?(@observer) }).to eq true
|
8
10
|
end
|
9
11
|
|
10
12
|
it "adds a callable observer" do
|
@@ -13,13 +15,13 @@ RSpec.shared_examples "a pipe" do
|
|
13
15
|
|
14
16
|
@pipe.add_observer @proc
|
15
17
|
|
16
|
-
expect(@pipe.is_observer?(@proc)).to eq true
|
18
|
+
expect(await { @pipe.is_observer?(@proc) }).to eq true
|
17
19
|
end
|
18
20
|
|
19
21
|
it "does not allow an observer without a #call method" do
|
20
22
|
@pipe = described_class.start
|
21
23
|
|
22
|
-
expect { @pipe.add_observer(Object.new) }.to raise_error(TypeError)
|
24
|
+
expect { await { @pipe.add_observer(Object.new) } }.to raise_error(TypeError)
|
23
25
|
end
|
24
26
|
|
25
27
|
it "removes an observer" do
|
@@ -28,10 +30,10 @@ RSpec.shared_examples "a pipe" do
|
|
28
30
|
|
29
31
|
@pipe.remove_observer @proc
|
30
32
|
|
31
|
-
expect(@pipe.is_observer?(@proc)).to eq false
|
33
|
+
expect(await { @pipe.is_observer?(@proc) }).to eq false
|
32
34
|
end
|
33
35
|
|
34
|
-
it "does not send notifications for objects
|
36
|
+
it "does not send notifications for objects which are not events" do
|
35
37
|
@pipe = described_class.start
|
36
38
|
@results = []
|
37
39
|
@observer = @pipe.add_observer do |event|
|
@@ -40,7 +42,7 @@ RSpec.shared_examples "a pipe" do
|
|
40
42
|
|
41
43
|
@pipe << Object.new
|
42
44
|
|
43
|
-
sleep 0.
|
45
|
+
sleep 0.1
|
44
46
|
expect(@results).to eq []
|
45
47
|
end
|
46
48
|
|
@@ -101,6 +103,6 @@ RSpec.shared_examples "a pipe" do
|
|
101
103
|
|
102
104
|
@pipe.shutdown
|
103
105
|
|
104
|
-
expect(@pipe.is_observer?(@observer)).to eq false
|
106
|
+
expect(await { @pipe.is_observer?(@observer) }).to eq false
|
105
107
|
end
|
106
108
|
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../../../lib/plumbing/actor/transporter"
|
3
|
+
|
4
|
+
RSpec.describe Plumbing::Actor::Transporter do
|
5
|
+
# standard:disable Lint/ConstantDefinitionInBlock
|
6
|
+
class Record
|
7
|
+
include GlobalID::Identification
|
8
|
+
attr_reader :id
|
9
|
+
def initialize id
|
10
|
+
@id = id
|
11
|
+
end
|
12
|
+
|
13
|
+
def == other
|
14
|
+
other.id == @id
|
15
|
+
end
|
16
|
+
end
|
17
|
+
# standard:enable Lint/ConstantDefinitionInBlock
|
18
|
+
before do
|
19
|
+
GlobalID.app = "rspec"
|
20
|
+
GlobalID::Locator.use :rspec do |gid, options|
|
21
|
+
Record.new gid.model_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "marshalling" do
|
26
|
+
it "passes simple arguments" do
|
27
|
+
@transporter = described_class.new
|
28
|
+
|
29
|
+
@transport = @transporter.marshal "Hello"
|
30
|
+
expect(@transport).to eq ["Hello"]
|
31
|
+
|
32
|
+
@transport = @transporter.marshal 1, 2, 3
|
33
|
+
expect(@transport).to eq [1, 2, 3]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "copies arrays" do
|
37
|
+
@transporter = described_class.new
|
38
|
+
|
39
|
+
@source = [[1, 2, 3], [:this, :that]]
|
40
|
+
|
41
|
+
@transport = @transporter.marshal(*@source)
|
42
|
+
expect(@transport).to eq @source
|
43
|
+
expect(@transport.first.object_id).to_not eq @source.first.object_id
|
44
|
+
expect(@transport.last.object_id).to_not eq @source.last.object_id
|
45
|
+
end
|
46
|
+
|
47
|
+
it "copies hashss" do
|
48
|
+
@transporter = described_class.new
|
49
|
+
|
50
|
+
@source = [{first: "1", second: 2}]
|
51
|
+
|
52
|
+
@transport = @transporter.marshal(*@source)
|
53
|
+
expect(@transport).to eq @source
|
54
|
+
expect(@transport.first.object_id).to_not eq @source.first.object_id
|
55
|
+
end
|
56
|
+
|
57
|
+
it "converts objects to Global ID strings" do
|
58
|
+
@transporter = described_class.new
|
59
|
+
|
60
|
+
@record = Record.new 123
|
61
|
+
@global_id = @record.to_global_id.to_s
|
62
|
+
|
63
|
+
@transport = @transporter.marshal @record
|
64
|
+
|
65
|
+
expect(@transport).to eq [@global_id]
|
66
|
+
end
|
67
|
+
|
68
|
+
it "converts objects within arrays to Global ID strings" do
|
69
|
+
@transporter = described_class.new
|
70
|
+
|
71
|
+
@record = Record.new 123
|
72
|
+
@global_id = @record.to_global_id.to_s
|
73
|
+
|
74
|
+
@transport = @transporter.marshal [:this, @record]
|
75
|
+
|
76
|
+
expect(@transport).to eq [[:this, @global_id]]
|
77
|
+
end
|
78
|
+
|
79
|
+
it "converts objects within hashes to Global ID strings" do
|
80
|
+
@transporter = described_class.new
|
81
|
+
|
82
|
+
@record = Record.new 123
|
83
|
+
@global_id = @record.to_global_id.to_s
|
84
|
+
|
85
|
+
@transport = @transporter.marshal this: "that", the_other: {embedded: @record}
|
86
|
+
|
87
|
+
expect(@transport).to eq [{this: "that", the_other: {embedded: @global_id}}]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "unmarshalling" do
|
92
|
+
it "passes simple arguments" do
|
93
|
+
@transporter = described_class.new
|
94
|
+
|
95
|
+
@transport = @transporter.unmarshal "Hello"
|
96
|
+
expect(@transport).to eq ["Hello"]
|
97
|
+
|
98
|
+
@transport = @transporter.unmarshal 1, 2, 3
|
99
|
+
expect(@transport).to eq [1, 2, 3]
|
100
|
+
end
|
101
|
+
|
102
|
+
it "passes arrays" do
|
103
|
+
@transporter = described_class.new
|
104
|
+
|
105
|
+
@transport = @transporter.unmarshal [1, 2, 3], [:this, :that]
|
106
|
+
|
107
|
+
expect(@transport.first.object_id).to_not eq [1, 2, 3]
|
108
|
+
expect(@transport.last.object_id).to_not eq [:this, :that]
|
109
|
+
end
|
110
|
+
|
111
|
+
it "passes hashss and keyword arguments" do
|
112
|
+
@transporter = described_class.new
|
113
|
+
|
114
|
+
@transport = @transporter.unmarshal first: "1", second: 2
|
115
|
+
expect(@transport).to eq [{first: "1", second: 2}]
|
116
|
+
end
|
117
|
+
|
118
|
+
it "passes mixtures of arrays and hashes" do
|
119
|
+
@transporter = described_class.new
|
120
|
+
|
121
|
+
@transport = @transporter.unmarshal :this, :that, first: "1", second: 2
|
122
|
+
expect(@transport).to eq [:this, :that, {first: "1", second: 2}]
|
123
|
+
end
|
124
|
+
|
125
|
+
it "converts Global ID strings to objects" do
|
126
|
+
@transporter = described_class.new
|
127
|
+
|
128
|
+
@record = Record.new "123"
|
129
|
+
@global_id = @record.to_global_id.to_s
|
130
|
+
|
131
|
+
@transport = @transporter.unmarshal @global_id
|
132
|
+
|
133
|
+
expect(@transport).to eq [@record]
|
134
|
+
end
|
135
|
+
|
136
|
+
it "converts Global ID strings within arrays to objects" do
|
137
|
+
@transporter = described_class.new
|
138
|
+
|
139
|
+
@record = Record.new "123"
|
140
|
+
@global_id = @record.to_global_id.to_s
|
141
|
+
|
142
|
+
@transport = @transporter.unmarshal :this, @global_id
|
143
|
+
|
144
|
+
expect(@transport).to eq [:this, @record]
|
145
|
+
end
|
146
|
+
|
147
|
+
it "converts Global ID strings within hashes to objects" do
|
148
|
+
@transporter = described_class.new
|
149
|
+
|
150
|
+
@record = Record.new "123"
|
151
|
+
@global_id = @record.to_global_id.to_s
|
152
|
+
|
153
|
+
@transport = @transporter.unmarshal this: "that", the_other: {embedded: @global_id}
|
154
|
+
|
155
|
+
expect(@transport).to eq [{this: "that", the_other: {embedded: @record}}]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
require_relative "../../lib/plumbing/actor/async"
|
4
|
+
require_relative "../../lib/plumbing/actor/threaded"
|
5
|
+
require_relative "../../lib/plumbing/actor/rails"
|
6
|
+
|
7
|
+
RSpec.describe Plumbing::Actor do
|
8
|
+
# standard:disable Lint/ConstantDefinitionInBlock
|
9
|
+
class Counter
|
10
|
+
include Plumbing::Actor
|
11
|
+
async :name, :count, :slow_query, "slowly_increment", "raises_error"
|
12
|
+
attr_reader :name, :count
|
13
|
+
|
14
|
+
def initialize name, initial_value: 0
|
15
|
+
@name = name
|
16
|
+
@count = initial_value
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def slowly_increment
|
22
|
+
sleep 0.2
|
23
|
+
@count += 1
|
24
|
+
end
|
25
|
+
|
26
|
+
def slow_query
|
27
|
+
sleep 0.2
|
28
|
+
@count
|
29
|
+
end
|
30
|
+
|
31
|
+
def raises_error = raise "I'm an error"
|
32
|
+
end
|
33
|
+
|
34
|
+
class StepCounter < Counter
|
35
|
+
async :step_value
|
36
|
+
attr_reader :step_value
|
37
|
+
|
38
|
+
def initialize name, initial_value: 0, step_value: 5
|
39
|
+
super(name, initial_value: initial_value)
|
40
|
+
@step_value = step_value
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def slowly_increment
|
46
|
+
sleep 0.2
|
47
|
+
@count += @step_value
|
48
|
+
end
|
49
|
+
|
50
|
+
def failing_query
|
51
|
+
raise "I'm a failure"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
# standard:enable Lint/ConstantDefinitionInBlock
|
55
|
+
|
56
|
+
it "knows which async messages are understood" do
|
57
|
+
expect(Counter.async_messages).to eq [:name, :count, :slow_query, :slowly_increment, :raises_error]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "reuses existing proxy classes" do
|
61
|
+
@counter = Counter.start "inline counter", initial_value: 100
|
62
|
+
@proxy_class = @counter.class
|
63
|
+
|
64
|
+
@counter = Counter.start "another inline counter", initial_value: 200
|
65
|
+
expect(@counter.class).to eq @proxy_class
|
66
|
+
end
|
67
|
+
|
68
|
+
it "includes commands and queries from the superclass" do
|
69
|
+
expect(StepCounter.async_messages).to eq [:name, :count, :slow_query, :slowly_increment, :raises_error, :step_value]
|
70
|
+
|
71
|
+
@step_counter = StepCounter.start "step counter", initial_value: 100, step_value: 10
|
72
|
+
|
73
|
+
expect(@step_counter.count.await).to eq 100
|
74
|
+
expect(@step_counter.step_value.await).to eq 10
|
75
|
+
@step_counter.slowly_increment
|
76
|
+
expect(@step_counter.count.await).to eq 110
|
77
|
+
end
|
78
|
+
|
79
|
+
context "inline" do
|
80
|
+
around :example do |example|
|
81
|
+
Plumbing.configure mode: :inline, &example
|
82
|
+
end
|
83
|
+
|
84
|
+
it "returns the result from a message immediately" do
|
85
|
+
@counter = Counter.start "inline counter", initial_value: 100
|
86
|
+
@time = Time.now
|
87
|
+
|
88
|
+
expect(@counter.name.await).to eq "inline counter"
|
89
|
+
expect(@counter.count.await).to eq 100
|
90
|
+
expect(Time.now - @time).to be < 0.1
|
91
|
+
|
92
|
+
expect(@counter.slow_query.await).to eq 100
|
93
|
+
expect(Time.now - @time).to be > 0.1
|
94
|
+
end
|
95
|
+
|
96
|
+
it "sends all commands immediately" do
|
97
|
+
@counter = Counter.start "inline counter", initial_value: 100
|
98
|
+
@time = Time.now
|
99
|
+
|
100
|
+
@counter.slowly_increment
|
101
|
+
|
102
|
+
expect(@counter.count.await).to eq 101
|
103
|
+
expect(Time.now - @time).to be > 0.1
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
[:threaded, :async].each do |mode|
|
108
|
+
context mode.to_s do
|
109
|
+
around :example do |example|
|
110
|
+
Sync do
|
111
|
+
Plumbing.configure mode: mode, &example
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it "performs queries in the background and waits for the response" do
|
116
|
+
@counter = Counter.start "async counter", initial_value: 100
|
117
|
+
@time = Time.now
|
118
|
+
|
119
|
+
expect(@counter.name.await).to eq "async counter"
|
120
|
+
expect(@counter.count.await).to eq 100
|
121
|
+
expect(Time.now - @time).to be < 0.1
|
122
|
+
|
123
|
+
expect(@counter.slow_query.await).to eq 100
|
124
|
+
expect(Time.now - @time).to be > 0.1
|
125
|
+
end
|
126
|
+
|
127
|
+
it "performs queries ignoring the response and returning immediately" do
|
128
|
+
@counter = Counter.start "threaded counter", initial_value: 100
|
129
|
+
@time = Time.now
|
130
|
+
|
131
|
+
@counter.slow_query
|
132
|
+
|
133
|
+
expect(Time.now - @time).to be < 0.1
|
134
|
+
end
|
135
|
+
|
136
|
+
it "performs commands in the background and returning immediately" do
|
137
|
+
@counter = Counter.start "threaded counter", initial_value: 100
|
138
|
+
@time = Time.now
|
139
|
+
|
140
|
+
@counter.slowly_increment
|
141
|
+
expect(Time.now - @time).to be < 0.1
|
142
|
+
|
143
|
+
# wait for the background task to complete
|
144
|
+
expect(101).to become_equal_to { @counter.count.await }
|
145
|
+
expect(Time.now - @time).to be > 0.1
|
146
|
+
end
|
147
|
+
|
148
|
+
it "re-raises exceptions when checking the result" do
|
149
|
+
@counter = Counter.start "failure"
|
150
|
+
|
151
|
+
expect { @counter.raises_error.await }.to raise_error "I'm an error"
|
152
|
+
end
|
153
|
+
|
154
|
+
it "does not raise exceptions if ignoring the result" do
|
155
|
+
@counter = Counter.start "failure"
|
156
|
+
|
157
|
+
expect { @counter.raises_error }.not_to raise_error
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context "threaded" do
|
163
|
+
around :example do |example|
|
164
|
+
Plumbing.configure mode: :threaded, &example
|
165
|
+
end
|
166
|
+
|
167
|
+
# standard:disable Lint/ConstantDefinitionInBlock
|
168
|
+
class Record
|
169
|
+
include GlobalID::Identification
|
170
|
+
attr_reader :id
|
171
|
+
def initialize id
|
172
|
+
@id = id
|
173
|
+
end
|
174
|
+
|
175
|
+
def == other
|
176
|
+
other.id == @id
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
class Actor
|
181
|
+
include Plumbing::Actor
|
182
|
+
async :get_object_id, :get_object
|
183
|
+
|
184
|
+
private def get_object_id(record) = record.object_id
|
185
|
+
private def get_object(record) = record
|
186
|
+
end
|
187
|
+
# standard:enable Lint/ConstantDefinitionInBlock
|
188
|
+
|
189
|
+
it "packs and unpacks arguments when sending them across threads" do
|
190
|
+
@actor = Actor.start
|
191
|
+
@record = Record.new "999"
|
192
|
+
|
193
|
+
@object_id = @actor.get_object_id(@record).await
|
194
|
+
|
195
|
+
expect(@object_id).to_not eq @record.object_id
|
196
|
+
end
|
197
|
+
|
198
|
+
it "packs and unpacks results when sending them across threads" do
|
199
|
+
@actor = Actor.start
|
200
|
+
@record = Record.new "999"
|
201
|
+
|
202
|
+
@object = @actor.get_object(@record).await
|
203
|
+
|
204
|
+
expect(@object.id).to eq @record.id
|
205
|
+
expect(@object.object_id).to_not eq @record.object_id
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: standard-procedure-plumbing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rahoul Baruah
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-09-
|
12
|
-
dependencies:
|
11
|
+
date: 2024-09-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: globalid
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
description: A composable event pipeline and sequential pipelines of operations
|
14
28
|
email:
|
15
29
|
- rahoulb@echodek.co
|
@@ -20,6 +34,13 @@ files:
|
|
20
34
|
- README.md
|
21
35
|
- Rakefile
|
22
36
|
- lib/plumbing.rb
|
37
|
+
- lib/plumbing/actor.rb
|
38
|
+
- lib/plumbing/actor/async.rb
|
39
|
+
- lib/plumbing/actor/inline.rb
|
40
|
+
- lib/plumbing/actor/kernel.rb
|
41
|
+
- lib/plumbing/actor/rails.rb
|
42
|
+
- lib/plumbing/actor/threaded.rb
|
43
|
+
- lib/plumbing/actor/transporter.rb
|
23
44
|
- lib/plumbing/config.rb
|
24
45
|
- lib/plumbing/custom_filter.rb
|
25
46
|
- lib/plumbing/error.rb
|
@@ -35,26 +56,21 @@ files:
|
|
35
56
|
- lib/plumbing/rubber_duck/object.rb
|
36
57
|
- lib/plumbing/rubber_duck/proxy.rb
|
37
58
|
- lib/plumbing/types.rb
|
38
|
-
- lib/plumbing/valve.rb
|
39
|
-
- lib/plumbing/valve/async.rb
|
40
|
-
- lib/plumbing/valve/inline.rb
|
41
|
-
- lib/plumbing/valve/message.rb
|
42
|
-
- lib/plumbing/valve/rails.rb
|
43
|
-
- lib/plumbing/valve/threaded.rb
|
44
59
|
- lib/plumbing/version.rb
|
45
60
|
- spec/become_equal_to_matcher.rb
|
61
|
+
- spec/examples/actor_spec.rb
|
46
62
|
- spec/examples/pipe_spec.rb
|
47
63
|
- spec/examples/pipeline_spec.rb
|
48
64
|
- spec/examples/rubber_duck_spec.rb
|
49
|
-
- spec/examples/valve_spec.rb
|
50
65
|
- spec/plumbing/a_pipe.rb
|
66
|
+
- spec/plumbing/actor/transporter_spec.rb
|
67
|
+
- spec/plumbing/actor_spec.rb
|
51
68
|
- spec/plumbing/custom_filter_spec.rb
|
52
69
|
- spec/plumbing/filter_spec.rb
|
53
70
|
- spec/plumbing/junction_spec.rb
|
54
71
|
- spec/plumbing/pipe_spec.rb
|
55
72
|
- spec/plumbing/pipeline_spec.rb
|
56
73
|
- spec/plumbing/rubber_duck_spec.rb
|
57
|
-
- spec/plumbing/valve_spec.rb
|
58
74
|
- spec/plumbing_spec.rb
|
59
75
|
- spec/spec_helper.rb
|
60
76
|
homepage: https://github.com/standard-procedure/plumbing
|
data/lib/plumbing/valve/async.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
require "async"
|
2
|
-
require "async/semaphore"
|
3
|
-
require "timeout"
|
4
|
-
|
5
|
-
module Plumbing
|
6
|
-
module Valve
|
7
|
-
class Async
|
8
|
-
attr_reader :target
|
9
|
-
|
10
|
-
def initialize target
|
11
|
-
@target = target
|
12
|
-
@queue = []
|
13
|
-
@semaphore = ::Async::Semaphore.new(1)
|
14
|
-
end
|
15
|
-
|
16
|
-
# Ask the target to answer the given message
|
17
|
-
def ask(message, *args, **params, &block)
|
18
|
-
task = @semaphore.async do
|
19
|
-
@target.send message, *args, **params, &block
|
20
|
-
end
|
21
|
-
Timeout.timeout(timeout) do
|
22
|
-
task.wait
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
# Tell the target to execute the given message
|
27
|
-
def tell(message, *args, **params, &block)
|
28
|
-
@semaphore.async do |task|
|
29
|
-
@target.send message, *args, **params, &block
|
30
|
-
rescue
|
31
|
-
nil
|
32
|
-
end
|
33
|
-
nil
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def timeout
|
39
|
-
Plumbing.config.timeout
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Plumbing
|
2
|
-
module Valve
|
3
|
-
class Inline
|
4
|
-
def initialize target
|
5
|
-
@target = target
|
6
|
-
end
|
7
|
-
|
8
|
-
# Ask the target to answer the given message
|
9
|
-
def ask(message, ...)
|
10
|
-
@target.send(message, ...)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Tell the target to execute the given message
|
14
|
-
def tell(message, ...)
|
15
|
-
@target.send(message, ...)
|
16
|
-
nil
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|