standard-procedure-plumbing 0.4.1 → 0.4.3

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
  SHA256:
3
- metadata.gz: ace6c01658b88c08c34d48406f983fdad449bc4f122b8dfed026853841b48d35
4
- data.tar.gz: 96b4458d0c667e10bb47fb8881de2e21df0ff40243cf07ff30e2e22f29892625
3
+ metadata.gz: 95f2fc92882bb116a50fb4406b8d905b6783bfd0b2f74a4229162fd26a920668
4
+ data.tar.gz: a0db08496ca520d9ae6baf50495395b3f943869cc07105b8d5ef7cefc054f8bf
5
5
  SHA512:
6
- metadata.gz: a5ee7af05314dbb45d9f46a302f6102f93237334224f82f1c34cdd5c252829039bf6b4bc18a562fcdb5d76a8ca229a484b0f3d3e123b7e5efd46d302f50c72b4
7
- data.tar.gz: 005f6cee1eb899207659955ea5a4179133c65e07db913e8f3f9c730cfca8947684927c9b99b675e9f54dc4ea4820159d709d61b146113a993783cec2a0c5842c
6
+ metadata.gz: 976815454b96a52880605f34fc7d7ae801259bedaa7807c148f9edc951e9e8766d35e9cc0988d2f572aa7076bf78e9b90a666468b1438b0b80abe6cb3e3d9947
7
+ data.tar.gz: 6c9852305cf8ac858d853cdeac89c57c3424838d5ee51a130a989210ffdd8337d393dd710f61d8cf0a3212f4027383840c7919e44d61c6c86e8bfb9af53eac8f
data/README.md CHANGED
@@ -469,6 +469,8 @@ You can also use the same `@object.as type` to type-check instances against modu
469
469
 
470
470
  ## Installation
471
471
 
472
+ Note: this gem is licensed under the [LGPL](/LICENCE). This may or may not make it unsuitable for use by you or your company.
473
+
472
474
  Install the gem and add to the application's Gemfile by executing:
473
475
 
474
476
  ```sh
@@ -14,9 +14,9 @@ module Plumbing
14
14
  end
15
15
 
16
16
  # Send the message to the target and wrap the result
17
- def send_message message_name, *args, &block
17
+ def send_message(message_name, *, **, &)
18
18
  task = @semaphore.async do
19
- @target.send message_name, *args, &block
19
+ @target.send(message_name, *, **, &)
20
20
  end
21
21
  Result.new(task)
22
22
  end
@@ -28,9 +28,7 @@ module Plumbing
28
28
 
29
29
  def within_actor? = true
30
30
 
31
- def stop
32
- # do nothing
33
- end
31
+ def stop = nil
34
32
 
35
33
  Result = Data.define(:task) do
36
34
  def value
@@ -6,8 +6,8 @@ module Plumbing
6
6
  end
7
7
 
8
8
  # Send the message to the target and wrap the result
9
- def send_message(message_name, *, &)
10
- value = @target.send(message_name, *, &)
9
+ def send_message(message_name, *, **, &)
10
+ value = @target.send(message_name, *, **, &)
11
11
  Result.new(value)
12
12
  rescue => ex
13
13
  Result.new(ex)
@@ -20,9 +20,7 @@ module Plumbing
20
20
 
21
21
  def within_actor? = true
22
22
 
23
- def stop
24
- # do nothing
25
- end
23
+ def stop = nil
26
24
 
27
25
  Result = Data.define(:result) do
28
26
  def value = result.is_a?(Exception) ? raise(result) : result
@@ -5,8 +5,8 @@ module Plumbing
5
5
  class Rails < Threaded
6
6
  protected
7
7
 
8
- def future(&)
9
- Concurrent::Promises.future do
8
+ def in_context(&)
9
+ super do
10
10
  Rails.application.executor.wrap(&)
11
11
  end
12
12
  end
@@ -16,12 +16,10 @@ module Plumbing
16
16
  end
17
17
 
18
18
  # Send the message to the target and wrap the result
19
- def send_message message_name, *args, &block
20
- Message.new(@target, message_name, Plumbing::Actor.transporter.marshal(*args), block, Concurrent::MVar.new).tap do |message|
21
- @mutex.synchronize do
22
- @queue << message
23
- send_messages if @queue.any?
24
- end
19
+ def send_message(message_name, *args, **params, &block)
20
+ Message.new(@target, message_name, Plumbing::Actor.transporter.marshal(*args, **params), block, Concurrent::MVar.new).tap do |message|
21
+ @queue << message
22
+ send_messages
25
23
  end
26
24
  end
27
25
 
@@ -38,15 +36,18 @@ module Plumbing
38
36
 
39
37
  protected
40
38
 
41
- def future(&) = Concurrent::Promises.future(&)
39
+ def in_context(&)
40
+ Concurrent::Promises.future do
41
+ @mutex.synchronize(&)
42
+ end
43
+ end
42
44
 
43
45
  private
44
46
 
45
47
  def send_messages
46
- future do
47
- @mutex.synchronize do
48
- message = @queue.shift
49
- message&.call
48
+ in_context do
49
+ while (message = @queue.shift)
50
+ message.call
50
51
  end
51
52
  end
52
53
  end
@@ -64,8 +64,8 @@ module Plumbing
64
64
  def build_proxy_class
65
65
  Class.new(proxy_base_class).tap do |proxy_class|
66
66
  async_messages.each do |message|
67
- proxy_class.define_method message do |*args, &block|
68
- send_message(message, *args, &block)
67
+ proxy_class.define_method message do |*args, **params, &block|
68
+ send_message(message, *args, **params, &block)
69
69
  end
70
70
  end
71
71
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plumbing
4
- VERSION = "0.4.1"
4
+ VERSION = "0.4.3"
5
5
  end
@@ -112,39 +112,115 @@ RSpec.describe Plumbing::Actor do
112
112
 
113
113
  def do_safety_check = @on_safety_check&.call
114
114
  end
115
- # standard:enable Lint/ConstantDefinitionInBlock
116
115
 
117
- it "knows which async messages are understood" do
118
- expect(Counter.async_messages).to eq [:name, :count, :slow_query, :slowly_increment, :raises_error]
119
- end
116
+ class ParameterHandler
117
+ include Plumbing::Actor
118
+ async :set_values, :args, :params, :block
119
+ attr_reader :args, :params, :block
120
+
121
+ def initialize
122
+ @args = nil
123
+ @params = nil
124
+ @block = nil
125
+ end
120
126
 
121
- it "reuses existing proxy classes" do
122
- @counter = Counter.start "inline counter", initial_value: 100
123
- @proxy_class = @counter.class
127
+ private
124
128
 
125
- @counter = Counter.start "another inline counter", initial_value: 200
126
- expect(@counter.class).to eq @proxy_class
129
+ def set_values *args, **params, &block
130
+ @args = args
131
+ @params = params
132
+ @block = block
133
+ end
127
134
  end
135
+ # standard:enable Lint/ConstantDefinitionInBlock
136
+
137
+ [:inline, :async, :threaded].each do |mode|
138
+ context "In #{mode} mode" do
139
+ it "knows which async messages are understood" do
140
+ expect(Counter.async_messages).to eq [:name, :count, :slow_query, :slowly_increment, :raises_error]
141
+ end
128
142
 
129
- it "includes async messages from the superclass" do
130
- expect(StepCounter.async_messages).to eq [:name, :count, :slow_query, :slowly_increment, :raises_error, :step_value]
143
+ it "reuses existing proxy classes" do
144
+ @counter = Counter.start "inline counter", initial_value: 100
145
+ @proxy_class = @counter.class
131
146
 
132
- @step_counter = StepCounter.start "step counter", initial_value: 100, step_value: 10
147
+ @counter = Counter.start "another inline counter", initial_value: 200
148
+ expect(@counter.class).to eq @proxy_class
149
+ end
133
150
 
134
- expect(@step_counter.count.value).to eq 100
135
- expect(@step_counter.step_value.value).to eq 10
136
- @step_counter.slowly_increment
137
- expect(@step_counter.count.value).to eq 110
138
- end
151
+ it "includes async messages from the superclass" do
152
+ expect(StepCounter.async_messages).to eq [:name, :count, :slow_query, :slowly_increment, :raises_error, :step_value]
153
+
154
+ @step_counter = StepCounter.start "step counter", initial_value: 100, step_value: 10
155
+
156
+ expect(@step_counter.count.value).to eq 100
157
+ expect(@step_counter.step_value.value).to eq 10
158
+ @step_counter.slowly_increment
159
+ expect(@step_counter.count.value).to eq 110
160
+ end
161
+
162
+ it "can access its own proxy" do
163
+ @actor = WhoAmI.start
139
164
 
140
- it "can access its own proxy" do
141
- @actor = WhoAmI.start
165
+ expect(await { @actor.me_as_self }).to_not eq @actor
166
+ expect(await { @actor.me_as_actor }).to eq @actor
167
+ end
168
+ it "sends a single positional parameter" do
169
+ @parameter_handler = ParameterHandler.start
170
+
171
+ @parameter_handler.set_values "this"
172
+ expect(await { @parameter_handler.args }).to eq ["this"]
173
+ end
142
174
 
143
- expect(await { @actor.me_as_self }).to_not eq @actor
144
- expect(await { @actor.me_as_actor }).to eq @actor
175
+ it "sends multiple positional parameters" do
176
+ @parameter_handler = ParameterHandler.start
177
+
178
+ @parameter_handler.set_values "this", "that"
179
+ expect(await { @parameter_handler.args }).to eq ["this", "that"]
180
+ end
181
+
182
+ it "sends keyword parameters" do
183
+ @parameter_handler = ParameterHandler.start
184
+
185
+ @parameter_handler.set_values something: "for nothing", cat: "dog", number: 123
186
+ expect(await { @parameter_handler.params }).to eq({something: "for nothing", cat: "dog", number: 123})
187
+ end
188
+
189
+ it "sends a mix of positional and keyword parameters" do
190
+ @parameter_handler = ParameterHandler.start
191
+
192
+ @parameter_handler.set_values "what do you say", 123, something: "for nothing"
193
+ expect(await { @parameter_handler.args }).to eq ["what do you say", 123]
194
+ expect(await { @parameter_handler.params }).to eq({something: "for nothing"})
195
+ end
196
+
197
+ it "sends a block parameter" do
198
+ @parameter_handler = ParameterHandler.start
199
+
200
+ @parameter_handler.set_values do
201
+ "HELLO"
202
+ end
203
+
204
+ @block = await { @parameter_handler.block }
205
+ expect(@block.call).to eq "HELLO"
206
+ end
207
+
208
+ it "sends a mix of positional and keyword parameters with a block" do
209
+ @parameter_handler = ParameterHandler.start
210
+
211
+ @parameter_handler.set_values "what do you say", 123, something: "for nothing" do
212
+ "BOOM"
213
+ end
214
+
215
+ expect(await { @parameter_handler.args }).to eq ["what do you say", 123]
216
+ expect(await { @parameter_handler.params }).to eq({something: "for nothing"})
217
+ @block = await { @parameter_handler.block }
218
+ expect(@block.call).to eq "BOOM"
219
+ end
220
+ end
145
221
  end
146
222
 
147
- context "inline" do
223
+ context "Inline mode only" do
148
224
  around :example do |example|
149
225
  Plumbing.configure mode: :inline, &example
150
226
  end
@@ -182,7 +258,7 @@ RSpec.describe Plumbing::Actor do
182
258
  end
183
259
 
184
260
  [:threaded, :async].each do |mode|
185
- context mode.to_s do
261
+ context "Asynchronously (#{mode})" do
186
262
  around :example do |example|
187
263
  Sync do
188
264
  Plumbing.configure mode: mode, &example
@@ -246,7 +322,7 @@ RSpec.describe Plumbing::Actor do
246
322
  end
247
323
  end
248
324
 
249
- context "threaded" do
325
+ context "Threaded mode only" do
250
326
  around :example do |example|
251
327
  Plumbing.configure mode: :threaded, &example
252
328
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard-procedure-plumbing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.3
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-16 00:00:00.000000000 Z
11
+ date: 2024-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: globalid