fiber_connection_pool 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +57 -6
- data/lib/fiber_connection_pool.rb +25 -21
- metadata +14 -19
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 11dbf1d76b0a43dd34325a66e350d16d0bd27ded
|
4
|
+
data.tar.gz: b1af865a443903cca63885dc8f3a262e13dc96b6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3c6e61ff7b08b2163cf10057c9d2e84be87577e6d5fcdee5e90472f560f77fef2174da09cbe40a0e886bc8b9c580460f7e92a1f2e0d32b965acb2f220004ee4e
|
7
|
+
data.tar.gz: 01659369b1a7079d945c048df1330e6ba02245af2f86e2626014a514dc7e3609f053b6453e9e4f7d68f7aabd8312cbf2d3d29361d8e39609b9fcad6710bcd604
|
data/README.md
CHANGED
@@ -157,10 +157,14 @@ it from the fiber itself, worry should not.
|
|
157
157
|
Save data
|
158
158
|
-------------------
|
159
159
|
|
160
|
-
Sometimes we need to get something more than de return value from the `query_me` call,
|
161
|
-
|
162
|
-
|
163
|
-
|
160
|
+
Sometimes we need to get something more than de return value from the `query_me` call,
|
161
|
+
but that _something_ is related to _that_ call on _that_ connection.
|
162
|
+
For example, maybe you need to call `affected_rows` right after the query was
|
163
|
+
made on that particular connection.
|
164
|
+
If you make that extra calls on the `pool` object, it will acquire a new connection
|
165
|
+
from the pool an run on it. So it's useless.
|
166
|
+
There is a way to gather all that data from the connection so we can work on it,
|
167
|
+
but also release the connection for other fiber to use it.
|
164
168
|
|
165
169
|
``` ruby
|
166
170
|
# define the pool
|
@@ -186,7 +190,8 @@ puts pool.gathered_data
|
|
186
190
|
|
187
191
|
You must access the gathered data from the same fiber that triggered its gathering.
|
188
192
|
Also any new call to `query_me` or any other method from the connection would execute the block again,
|
189
|
-
overwriting that position on the hash (unless you code to prevent it, of course).
|
193
|
+
overwriting that position on the hash (unless you code to prevent it, of course).
|
194
|
+
Usually you would use the gathered data
|
190
195
|
right after you made the query that generated it. But you could:
|
191
196
|
|
192
197
|
``` ruby
|
@@ -196,12 +201,58 @@ pool.save_data(:affected_rows) do |connection, method, args|
|
|
196
201
|
end
|
197
202
|
```
|
198
203
|
|
199
|
-
You can define as much `save_data` blocks as you want, and run any wonder ruby lets you.
|
204
|
+
You can define as much `save_data` blocks as you want, and run any wonder ruby lets you.
|
205
|
+
But great power comes with great responsability.
|
200
206
|
You must consider that any requests for saving data are executed for _every call_ on the pool from that fiber.
|
201
207
|
So keep it stupid simple, and blindly fast. At least as much as you can. That would affect performance otherwise.
|
202
208
|
|
203
209
|
Any gathered_data is released when the fiber is dead, but as you must access it from the fiber itself, worry should not.
|
204
210
|
|
211
|
+
|
212
|
+
Manual acquire
|
213
|
+
-------------------
|
214
|
+
|
215
|
+
Sometimes you may need to execute a sequence of methods on the same instance.
|
216
|
+
Then you should use manually acquire the connection from the pool. But then you are entirely
|
217
|
+
responsible of releasing it back again into the pool. See this example:
|
218
|
+
|
219
|
+
``` ruby
|
220
|
+
def transaction
|
221
|
+
@pool.acquire # reserve one instance for this fiber
|
222
|
+
@pool.query 'BEGIN' # start SQL transaction
|
223
|
+
|
224
|
+
yield # perform queries inside the transaction
|
225
|
+
|
226
|
+
@pool.query 'COMMIT' # confirm it
|
227
|
+
rescue => ex
|
228
|
+
@pool.query 'ROLLBACK' # discard it
|
229
|
+
raise ex
|
230
|
+
ensure
|
231
|
+
@pool.release # always release it back
|
232
|
+
end
|
233
|
+
|
234
|
+
transaction do
|
235
|
+
@pool.query 'UPDATE ...'
|
236
|
+
@pool.query 'SELECT ...'
|
237
|
+
end
|
238
|
+
```
|
239
|
+
|
240
|
+
When you call `acquire`, one connection will be taken out of the pool and reserved for exclusive use
|
241
|
+
of the current fiber. Every call you make to the pool from this fiber will be using the same connection instance,
|
242
|
+
until `release` is called. Then it's put back into the pool and made available for the other fibers.
|
243
|
+
|
244
|
+
If for some reason `release` is not called, then the connection will remain unavailable for the other
|
245
|
+
fibers until the death of the fiber that acquired it. Then it's returned to the pool. That's a garbage
|
246
|
+
collecting mechanism, not to rely on for performance. _You should definitely ensure_ you call `release`.
|
247
|
+
|
248
|
+
Notice that when you use `with_failed_connection` you may lose the actual instance.
|
249
|
+
Remember that `with_failed_connection` replaces the failing connection with the return value of the given block.
|
250
|
+
Only if you return the same instance you will not lose it.
|
251
|
+
Sometimes even that will not be enough, just look at the `transaction` example.
|
252
|
+
If anything raises before the `COMMIT`, it's not so easy to avoid being forced
|
253
|
+
to start the whole transaction all over again, whether you lost the actual instance or not.
|
254
|
+
|
255
|
+
|
205
256
|
Supported Platforms
|
206
257
|
-------------------
|
207
258
|
|
@@ -2,13 +2,13 @@ require 'fiber'
|
|
2
2
|
require_relative 'fiber_connection_pool/exceptions'
|
3
3
|
|
4
4
|
class FiberConnectionPool
|
5
|
-
VERSION = '0.3.
|
5
|
+
VERSION = '0.3.1'
|
6
6
|
|
7
7
|
RESERVED_TTL_SECS = 30 # reserved cleanup trigger
|
8
8
|
SAVED_DATA_TTL_SECS = 30 # saved_data cleanup trigger
|
9
9
|
|
10
10
|
attr_accessor :saved_data, :treated_exceptions
|
11
|
-
|
11
|
+
|
12
12
|
attr_reader :size
|
13
13
|
|
14
14
|
# Initializes the pool with 'size' instances
|
@@ -18,7 +18,7 @@ class FiberConnectionPool
|
|
18
18
|
#
|
19
19
|
def initialize(opts)
|
20
20
|
raise ArgumentError.new('size > 0 is mandatory') if opts[:size].to_i <= 0
|
21
|
-
|
21
|
+
|
22
22
|
@size = opts[:size].to_i
|
23
23
|
|
24
24
|
@saved_data = {} # placeholder for requested save data
|
@@ -34,16 +34,6 @@ class FiberConnectionPool
|
|
34
34
|
@available = Array.new(@size) { yield }
|
35
35
|
end
|
36
36
|
|
37
|
-
# DEPRECATED: use save_data
|
38
|
-
def save_data_for_fiber
|
39
|
-
nil
|
40
|
-
end
|
41
|
-
|
42
|
-
# DEPRECATED: use release_data
|
43
|
-
def stop_saving_data_for_fiber
|
44
|
-
@saved_data.delete Fiber.current
|
45
|
-
end
|
46
|
-
|
47
37
|
# Add a save_data request to the pool.
|
48
38
|
# The given block will be executed after each successful
|
49
39
|
# call to -any- method on the connection.
|
@@ -122,16 +112,19 @@ class FiberConnectionPool
|
|
122
112
|
# Raises NoReservedConnection if cannot find the failed connection instance.
|
123
113
|
#
|
124
114
|
def with_failed_connection
|
125
|
-
|
115
|
+
fiber = Fiber.current
|
116
|
+
bad_conn = @reserved[fiber]
|
126
117
|
raise NoReservedConnection.new if bad_conn.nil?
|
127
118
|
new_conn = yield bad_conn
|
128
119
|
@available.reject!{ |v| v == bad_conn }
|
129
120
|
@reserved.reject!{ |k,v| v == bad_conn }
|
130
|
-
|
131
|
-
#
|
132
|
-
|
133
|
-
|
134
|
-
|
121
|
+
|
122
|
+
# we should keep it if manually acquired,
|
123
|
+
# just in case it is still useful
|
124
|
+
if @keep_connection[fiber] then
|
125
|
+
@reserved[fiber] = new_conn
|
126
|
+
else
|
127
|
+
@available.unshift new_conn # or else release into the pool
|
135
128
|
end
|
136
129
|
end
|
137
130
|
|
@@ -154,8 +147,19 @@ class FiberConnectionPool
|
|
154
147
|
#
|
155
148
|
# Ex:
|
156
149
|
#
|
157
|
-
#
|
150
|
+
# def transaction
|
151
|
+
# @pool.acquire # reserve one instance for this fiber
|
152
|
+
# @pool.query 'BEGIN' # start SQL transaction
|
158
153
|
#
|
154
|
+
# yield # perform queries inside the transaction
|
155
|
+
#
|
156
|
+
# @pool.query 'COMMIT' # confirm it
|
157
|
+
# rescue => ex
|
158
|
+
# @pool.query 'ROLLBACK' # discard it
|
159
|
+
# raise ex
|
160
|
+
# ensure
|
161
|
+
# @pool.release # always release it back
|
162
|
+
# end
|
159
163
|
#
|
160
164
|
#
|
161
165
|
def acquire(fiber = nil, opts = { :keep => true })
|
@@ -179,7 +183,7 @@ class FiberConnectionPool
|
|
179
183
|
def release(fiber = nil)
|
180
184
|
fiber = Fiber.current if fiber.nil?
|
181
185
|
@keep_connection.delete fiber
|
182
|
-
|
186
|
+
|
183
187
|
@available.unshift @reserved.delete(fiber)
|
184
188
|
|
185
189
|
# try cleanup
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fiber_connection_pool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Ruben Caro
|
@@ -15,38 +14,35 @@ dependencies:
|
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: minitest
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
|
-
- -
|
18
|
+
- - '>='
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: '0'
|
23
21
|
type: :development
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
|
-
- -
|
25
|
+
- - '>='
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: '0'
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: rake
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
|
-
- -
|
32
|
+
- - '>='
|
37
33
|
- !ruby/object:Gem::Version
|
38
34
|
version: '0'
|
39
35
|
type: :development
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
|
-
- -
|
39
|
+
- - '>='
|
45
40
|
- !ruby/object:Gem::Version
|
46
41
|
version: '0'
|
47
|
-
description:
|
48
|
-
|
49
|
-
|
42
|
+
description: |-
|
43
|
+
Fiber-based generic connection pool for Ruby, allowing
|
44
|
+
non-blocking IO behaviour on the same thread
|
45
|
+
as provided by EventMachine or Celluloid.
|
50
46
|
email:
|
51
47
|
- ruben.caro@lanuez.org
|
52
48
|
executables: []
|
@@ -85,27 +81,26 @@ files:
|
|
85
81
|
homepage: https://github.com/rubencaro/fiber_connection_pool
|
86
82
|
licenses:
|
87
83
|
- GPLv3
|
84
|
+
metadata: {}
|
88
85
|
post_install_message:
|
89
86
|
rdoc_options: []
|
90
87
|
require_paths:
|
91
88
|
- lib
|
92
89
|
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
-
none: false
|
94
90
|
requirements:
|
95
|
-
- -
|
91
|
+
- - '>='
|
96
92
|
- !ruby/object:Gem::Version
|
97
93
|
version: 1.9.2
|
98
94
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
-
none: false
|
100
95
|
requirements:
|
101
|
-
- -
|
96
|
+
- - '>='
|
102
97
|
- !ruby/object:Gem::Version
|
103
98
|
version: '0'
|
104
99
|
requirements: []
|
105
100
|
rubyforge_project:
|
106
|
-
rubygems_version:
|
101
|
+
rubygems_version: 2.0.6
|
107
102
|
signing_key:
|
108
|
-
specification_version:
|
103
|
+
specification_version: 4
|
109
104
|
summary: Fiber-based generic connection pool for Ruby
|
110
105
|
test_files:
|
111
106
|
- test/fiber_connection_pool_test.rb
|