fiber_connection_pool 0.3.0 → 0.3.1
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 +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
|