zoidberg 0.1.8 → 0.1.10
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/CHANGELOG.md +5 -0
- data/README.md +43 -4
- data/lib/zoidberg/pool.rb +2 -1
- data/lib/zoidberg/proxy/liberated.rb +7 -1
- data/lib/zoidberg/shell.rb +23 -8
- data/lib/zoidberg/supervise.rb +11 -0
- data/lib/zoidberg/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2bbdb961e871a0119977fa6b936a00ba8c0799ec
|
4
|
+
data.tar.gz: 8c83222944c0a2a60f0452d02dc72ce5b6b51bf1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3e02732c39a3611c5e17224b6b27b6303c19fd7eeb884cf0215dec496b8d38a494ea322c1c4840d237831581afb70c17a74f422e0131f04d10ff08e310014d9
|
7
|
+
data.tar.gz: 7f9d18e3ad68bd304a00581a807b929e05d9c472a5761734bac8b525c232189c2dd40e38a3d25fdf767de12c3c5a00e064d6ff0cc00b8356b867b3a25670001a
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -4,10 +4,12 @@
|
|
4
4
|
|
5
5
|
## About
|
6
6
|
|
7
|
-
Zoidberg
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
Zoidberg does a couple things. First, it can be a simple way to
|
8
|
+
provide implicit synchronization for thread safety in existing
|
9
|
+
code that is otherwise unsafe. Second, it can provide supervision
|
10
|
+
and pooling. This library is heavily inspired by Celluloid but,
|
11
|
+
while some APIs may look familiar, they do not share a familiar
|
12
|
+
implementation.
|
11
13
|
|
12
14
|
## Usage
|
13
15
|
|
@@ -120,6 +122,10 @@ and running it lots of times we get:
|
|
120
122
|
So this is pretty neat. We had a class that was shown to not be thread
|
121
123
|
safe. We tossed a module into that class. Now that class is thread safe.
|
122
124
|
|
125
|
+
### Should I really do this?
|
126
|
+
|
127
|
+
Maybe?
|
128
|
+
|
123
129
|
## Features
|
124
130
|
|
125
131
|
### Implicit Locking
|
@@ -129,6 +135,39 @@ behavior can be short circuited if the actual instance creates a thread
|
|
129
135
|
and calls a method on itself. Otherwise, all external access to the
|
130
136
|
instance will be automatically synchronized. Nifty.
|
131
137
|
|
138
|
+
This synchronization behavior comes from the shells included within
|
139
|
+
Zoidberg. There are two styles of shells available:
|
140
|
+
|
141
|
+
#### `Zoidberg::SoftShell`
|
142
|
+
|
143
|
+
This is the default shell used when the generic `Zoidberg::Shell` module
|
144
|
+
is included. It will wrap the raw instance and synchronize requests to
|
145
|
+
the instance.
|
146
|
+
|
147
|
+
#### `Zoidberg::HardShell`
|
148
|
+
|
149
|
+
This shell is still in development and not fully supported yet. The
|
150
|
+
hard shell is an implementation that is more reflective of the actor
|
151
|
+
model with a single thread wrapping an instance and synchronizing access.
|
152
|
+
|
153
|
+
### Supervision
|
154
|
+
|
155
|
+
Zoidberg can provide instance supervision. To enable supervision on a
|
156
|
+
class, include the module:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
|
160
|
+
class Fubar
|
161
|
+
include Zoidberg::Supervise
|
162
|
+
end
|
163
|
+
```
|
164
|
+
|
165
|
+
This will implicitly load the `Zoidberg::Shell` module and new instances
|
166
|
+
will be supervised. Supervision means Zoidberg will watch for unexpected
|
167
|
+
exceptions. What are "unexpected exceptions"? They are any exception raised
|
168
|
+
via `raise`. This will cause the instance to be torn down and a new instance
|
169
|
+
to be instantiated.
|
170
|
+
|
132
171
|
### Supervision
|
133
172
|
|
134
173
|
Zoidberg provides lazy supervision. There is no single supervisor. Instead
|
data/lib/zoidberg/pool.rb
CHANGED
@@ -78,7 +78,8 @@ module Zoidberg
|
|
78
78
|
# Used to proxy request to worker
|
79
79
|
def method_missing(*args, &block)
|
80
80
|
worker = _zoidberg_free_worker
|
81
|
-
|
81
|
+
current_self._release_lock!
|
82
|
+
worker.send(*args, &block)
|
82
83
|
end
|
83
84
|
|
84
85
|
# Find or wait for a free worker
|
@@ -74,7 +74,13 @@ module Zoidberg
|
|
74
74
|
# @return [TrueClas]
|
75
75
|
def _aquire_lock!
|
76
76
|
if(@_lock)
|
77
|
-
|
77
|
+
if(::ENV['ZOIDBERG_DEBUG'] == 'true')
|
78
|
+
::Timeout.timeout(::ENV.fetch('ZOIDBERG_DEBUG_TIMEOUT', 10).to_i) do
|
79
|
+
@_lock.lock unless @_locker == ::Thread.current
|
80
|
+
end
|
81
|
+
else
|
82
|
+
@_lock.lock unless @_locker == ::Thread.current
|
83
|
+
end
|
78
84
|
@_locker = ::Thread.current
|
79
85
|
@_locker_count += 1
|
80
86
|
_zoidberg_signal(:locked)
|
data/lib/zoidberg/shell.rb
CHANGED
@@ -10,16 +10,19 @@ module Zoidberg
|
|
10
10
|
|
11
11
|
class AsyncProxy
|
12
12
|
attr_reader :target
|
13
|
-
|
13
|
+
attr_reader :origin_proxy
|
14
|
+
def initialize(instance, proxy)
|
14
15
|
@target = instance
|
16
|
+
@origin_proxy = proxy
|
15
17
|
end
|
16
18
|
def method_missing(*args, &block)
|
17
19
|
target._zoidberg_thread(
|
18
20
|
Thread.new{
|
19
21
|
begin
|
20
22
|
target.send(*args, &block)
|
21
|
-
rescue
|
22
|
-
|
23
|
+
rescue StandardError, ScriptError => e
|
24
|
+
origin_proxy._zoidberg_unexpected_error(e)
|
25
|
+
raise
|
23
26
|
end
|
24
27
|
}
|
25
28
|
)
|
@@ -38,7 +41,7 @@ module Zoidberg
|
|
38
41
|
result = yield if block_given?
|
39
42
|
_zoidberg_proxy._aquire_lock!
|
40
43
|
result
|
41
|
-
rescue
|
44
|
+
rescue ::StandardError, ::ScriptError => e
|
42
45
|
_zoidberg_proxy._aquire_lock!
|
43
46
|
raise e
|
44
47
|
end
|
@@ -52,15 +55,27 @@ module Zoidberg
|
|
52
55
|
if(block_given?)
|
53
56
|
unless(locked)
|
54
57
|
thread = ::Thread.new do
|
55
|
-
|
58
|
+
begin
|
59
|
+
self.instance_exec(&block)
|
60
|
+
rescue ::StandardError, ::ScriptError => e
|
61
|
+
current_self._zoidberg_unexpected_error(e)
|
62
|
+
raise
|
63
|
+
end
|
56
64
|
end
|
57
65
|
else
|
58
|
-
thread = ::Thread.new
|
66
|
+
thread = ::Thread.new do
|
67
|
+
begin
|
68
|
+
current_self.instance_exec(&block)
|
69
|
+
rescue ::StandardError, ::ScriptError => e
|
70
|
+
current_self._zoidberg_unexpected_error(e)
|
71
|
+
raise
|
72
|
+
end
|
73
|
+
end
|
59
74
|
end
|
60
75
|
_zoidberg_thread(thread)
|
61
76
|
nil
|
62
77
|
else
|
63
|
-
::Zoidberg::SoftShell::AsyncProxy.new(locked ? current_self : self)
|
78
|
+
::Zoidberg::SoftShell::AsyncProxy.new(locked ? current_self : self, current_self)
|
64
79
|
end
|
65
80
|
end
|
66
81
|
|
@@ -232,7 +247,7 @@ module Zoidberg
|
|
232
247
|
# @param arg [Object] optional argument to transmit
|
233
248
|
# @return [TrueClass, FalseClass]
|
234
249
|
def signal(name, arg=nil)
|
235
|
-
|
250
|
+
_zoidberg_signal_interface.signal(*[name, arg].compact)
|
236
251
|
end
|
237
252
|
|
238
253
|
# Broadcast a signal to all waiters
|
data/lib/zoidberg/supervise.rb
CHANGED
@@ -6,6 +6,14 @@ module Zoidberg
|
|
6
6
|
# Customized exception type to wrap allowed errors
|
7
7
|
class AbortException < StandardError
|
8
8
|
attr_accessor :original_exception
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
if(original_exception)
|
12
|
+
"#{original_exception.class}: #{original_exception}"
|
13
|
+
else
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
9
17
|
end
|
10
18
|
|
11
19
|
module InstanceMethods
|
@@ -16,6 +24,9 @@ module Zoidberg
|
|
16
24
|
# @param e [Exception]
|
17
25
|
# @raises [AbortException]
|
18
26
|
def abort(e)
|
27
|
+
unless(e.is_a?(::Exception))
|
28
|
+
e = StandardError.new(e)
|
29
|
+
end
|
19
30
|
new_e = ::Zoidberg::Supervise::AbortException.new
|
20
31
|
new_e.original_exception = e
|
21
32
|
::Kernel.raise new_e
|
data/lib/zoidberg/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zoidberg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Roberts
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bogo
|