standard-procedure-async 0.1.2 → 0.2.1

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: 7c712b9a4a30138eb2c834422df444d22da7fbb16da26de1c1ec81db7cf15985
4
- data.tar.gz: 71dbabb9e071adb19146e17a275daaad05b0c9f242843b3d957908087f604a91
3
+ metadata.gz: 3aa258b93fc54c1232b652af7903b0fa85b4066aa09c442a4072c7d02d1fcf98
4
+ data.tar.gz: ef18826e86e742dcf96ac784dd654cbc9d07ce7aa71859fed83e58f488b87eca
5
5
  SHA512:
6
- metadata.gz: d84213a0def468819fbd0f63bc42d10a483b13790e1e3ee632b72d63d2d2d9438df2c7a3a586b6acbedba07ceaf8794b999c33cd53df4fb166cf0f5e5f998289
7
- data.tar.gz: 3972be625613fa325b92273d594f0e9c213fa4675e03181c39d60e334251f3fea7e6d369a9335dc639994aa182de8ead6785be04d011d21186c56b08badfc9fb
6
+ metadata.gz: 3c8168d2340e8e1ae2b5627f21c1f7a06adb0fb34845b4c1a4f0ba94e70fcd4609f2d502bd35441b0dd755ffc764a40e5ea69ae0949b20ddeb88a625bb8ea490
7
+ data.tar.gz: c0236a569b587399f419fed3b02b1991fd5d3bcbd286e514ee232f79a66e6b899b4ffbe798c622a5201c69896e1f8b8cb313c47bda2d74c75c9eaee81425a1e7
@@ -0,0 +1,3 @@
1
+ {
2
+ "tommasonegri.solargraph.internals.server.error" : true
3
+ }
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## [0.2.1] - 2023-12-24
2
+
3
+ - Bugfix: allow keyword arguments
4
+
1
5
  ## [0.1.2] - 2023-05-31
2
6
 
3
7
  - Added a timeout to `StandardProcedure::Async::Actor::Message` to prevent indefinite deadlocks.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- standard-procedure-async (0.1.2)
4
+ standard-procedure-async (0.2.1)
5
5
  concurrent-ruby (>= 1.0)
6
6
 
7
7
  GEM
@@ -119,6 +119,7 @@ GEM
119
119
 
120
120
  PLATFORMS
121
121
  arm64-darwin-22
122
+ arm64-darwin-23
122
123
  x86_64-linux
123
124
 
124
125
  DEPENDENCIES
data/LICENSE.txt CHANGED
@@ -1,21 +1,165 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2023 Rahoul Baruah
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
data/README.md CHANGED
@@ -75,14 +75,18 @@ end
75
75
 
76
76
  # Getting started
77
77
  puts @my_object.report_status # => internal message object
78
- puts @my_object.report_status.value # => :idle
78
+ @my_object.report_status.then do |value|
79
+ puts value # => :idle
80
+ end
79
81
  puts await { @my_object.report_status } # => :idle
80
82
  puts await { @my_object.greet } # => "Hello George"
83
+
81
84
  # Do some actual work
82
85
  await { @my_object.rename "Ringo" }
83
86
  puts await { @my_object.greet } # => "Hello Ringo"
84
87
  @my_object.rename "Paul" # Note: we didn't use await here - we'll talk about that later
85
88
  puts await { @my_object.greet } # => "Hello Paul"
89
+
86
90
  # Do something a bit more complex
87
91
  @initial_status = @my_object.do_some_long_running_task
88
92
  puts await { @initial_status } # => :in_progress
@@ -99,19 +103,32 @@ When defining `MyObject`, we use `async` instead of `def` for each method. For
99
103
 
100
104
  ### Awaiting the results from those methods
101
105
 
102
- The asynchronous wrapper always returns a internal message object that contains a [Concurrent::MVar](https://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/MVar.html). The MVar is empty until the actor has completed its work but if you need the return value from the method, there are two ways to access it.
106
+ The asynchronous wrapper always returns a internal message object that contains a [Concurrent::MVar](https://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/MVar.html). The MVar is empty until the actor has completed its work but if you need the return value from the method, there are a few ways to access it.
107
+
108
+ You can call `value` on the returned message. For convenience, `value` is also aliased as `get` and `await`.
109
+
110
+ ```ruby
111
+ # The following calls are all equivalent
112
+ @my_object.report_status.value
113
+ @my_object.report_status.get
114
+ @my_object.report_status.await
115
+ ```
103
116
 
104
- You can call `value` on the returned message.
117
+ You can use the global `await` method.
105
118
 
106
- Or you can use the `await` method (which is just a fancy wrapper around `value`).
119
+ ```ruby
120
+ puts await { @my_object.report_status }
121
+ ```
107
122
 
108
- In both cases the calling thread will block until the value is returned.
123
+ Or you can use the [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)-style resolution.
109
124
 
110
- In the example above, you can see how this works.
125
+ ```ruby
126
+ @my_object.report_status.then do |value|
127
+ puts value
128
+ end
129
+ ```
111
130
 
112
- - `puts @my_object.report_status` returns the internal message object itself, not any meaningful information.
113
- - `puts @my_object.report_status.value` blocks until the `report_status` method has completed and gives you the return value.
114
- - `puts await { @my_object.report_status }` is just a fancier (and potentially more readable and explicit) way of doing the same thing
131
+ In all cases the calling thread will block until the value is returned (or the `then` clause is triggered).
115
132
 
116
133
  ### The strict sequencing of asynchronous calls
117
134
 
@@ -148,6 +165,22 @@ This queueing has an important implication.
148
165
  If you are within an actor class, you can happily call async methods on other objects and `await` the results - because each actor has its own independent queue. But if you are calling your own methods, you must **never** call `await` (or call `value` on the returned message object).
149
166
 
150
167
  Picture this:
168
+
169
+ ```ruby
170
+ class ClassThatWillDeadlock
171
+ include StandardProcedure::Async::Actor
172
+
173
+ async :start_processing do
174
+ do_some_complicated_calculation.value
175
+ end
176
+
177
+ async :do_some_complicated_calculation do
178
+ sleep 1
179
+ 2 + 2
180
+ end
181
+ end
182
+ ```
183
+
151
184
  - Your actor has two `async` methods - `start_processing` and `do_complicated_calculation`
152
185
  - The main thread calls `start_processing` - so a message gets added to the head of the queue.
153
186
  - The actor's internal thread starts working on the message at the head of the queue, and `_start_processing` (the actual implementation) is called.
@@ -158,6 +191,22 @@ Picture this:
158
191
 
159
192
  To avoid this, if you ever need the return value from an internal `async` method, always call the implementation method: `_do_complicated_calculation` instead of `do_complicated_calculation`. This does not put anything on the queue and proceeds as a normal method call.
160
193
 
194
+ ```ruby
195
+ class ClassThatWillNotDeadlock
196
+ include StandardProcedure::Async::Actor
197
+
198
+ async :start_processing do
199
+ _do_some_complicated_calculation
200
+ end
201
+
202
+ async :do_some_complicated_calculation do
203
+ sleep 1
204
+ 2 + 2
205
+ end
206
+ end
207
+ ```
208
+
209
+
161
210
  As a fail-safe, any calls to `value` will also time-out after 30 seconds, returning Concurrent::MVar::TIMEOUT. If you need to override the timeout value you can use `message.value(timeout: value_in_seconds)`.
162
211
 
163
212
  ### The rules of using actors
@@ -200,10 +249,11 @@ Or install it yourself as:
200
249
  ## Development
201
250
 
202
251
  Coming soon
252
+
203
253
  ## Contributing
204
254
 
205
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/standard-procedure-async.
255
+ Bug reports and pull requests are welcome on GitHub at https://github.com/standard-procedure/async.
206
256
 
207
257
  ## License
208
258
 
209
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
259
+ The gem is available as open source under the terms of the [GNU Lesser General Public Licence](https://www.gnu.org/licenses/lgpl-3.0.txt). Paraphrased, this means you can use this library in your applications, but you must make give prominent notice that you are using this code, under this licence, and you must make the source to this library available if the software is distributed. Any changes you make _to this library_ must also be released under the LGPL and made available if the software is distributed. The licensing for your own code (that does not amend this library) is unaffected.
@@ -0,0 +1 @@
1
+ e9ecad84981421f13a69b6fa77964a1331488ddeb9581dcb2381d7daa4f6ae712f4a33edd1291b50fb70a49896a14b9b84dc6df4001a5c834ed561173685ba30
@@ -3,61 +3,70 @@
3
3
  require "concurrent/array"
4
4
  require "concurrent/mvar"
5
5
  require "concurrent/immutable_struct"
6
+ require_relative "promises"
6
7
 
7
- module StandardProcedure::Async
8
- module Actor
9
- def self.included base
10
- base.class_eval do
11
- extend ClassMethods
8
+ module StandardProcedure
9
+ module Async
10
+ module Actor
11
+ def self.included base
12
+ base.class_eval do
13
+ def self.async name, &implementation
14
+ name = name.to_sym
15
+ implementation_name = :"_#{name}"
12
16
 
13
- def initialize *args
14
- super
15
- @_messages = Concurrent::Array.new
17
+ define_method name do |*args, **params|
18
+ _add_message_to_queue(implementation_name, *args, **params)
19
+ end
20
+
21
+ define_method implementation_name do |*args, **params|
22
+ instance_exec(*args, **params, &implementation)
23
+ rescue => ex
24
+ ex
25
+ end
26
+ end
16
27
  end
17
28
  end
18
- end
19
29
 
20
- module ClassMethods
21
- def async name, &implementation
22
- name = name.to_sym
23
- implementation_name = :"_#{name}"
24
-
25
- define_method name.to_sym do |*args, &block|
26
- _add_message_to_queue(implementation_name, *args, &block)
27
- end
30
+ private
28
31
 
29
- define_method implementation_name do |*args, &block|
30
- implementation.call(*args, &block)
31
- end
32
+ def _messages
33
+ @_messages ||= Concurrent::Array.new
32
34
  end
33
- end
34
35
 
35
- private
36
-
37
- attr_reader :_messages
36
+ def _promises
37
+ @_promises ||= StandardProcedure::Async::Promises.new
38
+ end
38
39
 
39
- def _add_message_to_queue name, *args, &block
40
- message = Message.new(self, name, args, block, Concurrent::MVar.new)
41
- _messages << message
42
- _perform_messages if _messages.count == 1
43
- message
44
- end
40
+ def _add_message_to_queue name, *args, **params, &block
41
+ message = Message.new(self, name, args, params, block, Concurrent::MVar.new)
42
+ _messages << message
43
+ _perform_messages if _messages.count == 1
44
+ message
45
+ end
45
46
 
46
- def _perform_messages
47
- StandardProcedure::Async.promises.future do
48
- while (message = _messages.shift)
49
- message.call
47
+ def _perform_messages
48
+ _promises.future do
49
+ while (message = _messages.shift)
50
+ message.call
51
+ end
50
52
  end
51
53
  end
52
- end
53
54
 
54
- class Message < Concurrent::ImmutableStruct.new(:target, :name, :args, :block, :result)
55
- def value(timeout: 30)
56
- result.take(timeout)
57
- end
55
+ # nodoc:
56
+ class Message < Concurrent::ImmutableStruct.new(:target, :name, :args, :params, :block, :result)
57
+ def value(timeout: 30)
58
+ result.take(timeout)
59
+ end
60
+ alias_method :get, :value
61
+ alias_method :await, :value
62
+
63
+ def then &block
64
+ block&.call value
65
+ end
58
66
 
59
- def call
60
- result.put target.send(name, *args, &block)
67
+ def call
68
+ result.put target.send(name, *args, **params, &block)
69
+ end
61
70
  end
62
71
  end
63
72
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module StandardProcedure
4
4
  module Async
5
- VERSION = "0.1.2"
5
+ VERSION = "0.2.1"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard-procedure-async
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rahoul Baruah
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-31 00:00:00.000000000 Z
11
+ date: 2023-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -74,6 +74,7 @@ executables: []
74
74
  extensions: []
75
75
  extra_rdoc_files: []
76
76
  files:
77
+ - ".nova/Configuration.json"
77
78
  - ".rspec"
78
79
  - ".standard.yml"
79
80
  - CHANGELOG.md
@@ -82,6 +83,7 @@ files:
82
83
  - LICENSE.txt
83
84
  - README.md
84
85
  - Rakefile
86
+ - checksums/standard-procedure-async-0.2.0.gem.sha512
85
87
  - lib/standard_procedure/async.rb
86
88
  - lib/standard_procedure/async/actor.rb
87
89
  - lib/standard_procedure/async/await.rb
@@ -114,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
116
  - !ruby/object:Gem::Version
115
117
  version: '0'
116
118
  requirements: []
117
- rubygems_version: 3.4.12
119
+ rubygems_version: 3.4.22
118
120
  signing_key:
119
121
  specification_version: 4
120
122
  summary: A simple wrapper around Concurrent::Future to make concurrent-ruby Rails-friendly.