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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +57 -6
  3. data/lib/fiber_connection_pool.rb +25 -21
  4. 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, but that _something_ is related to _that_ call on _that_ connection.
161
- For example, maybe you need to call `affected_rows` right after the query was made on that particular connection.
162
- If you make that extra calls on the `pool` object, it will acquire a new connection from the pool an run on it. So it's useless.
163
- There is a way to gather all that data from the connection so we can work on it, but also release the connection for other fiber to use it.
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). Usually you would use the gathered data
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. But great power comes with great responsability.
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.0'
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
- bad_conn = @reserved[Fiber.current]
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
- @available.unshift new_conn
131
- # try to cleanup
132
- begin
133
- bad_conn.close
134
- rescue
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.0
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: ! "Fiber-based generic connection pool for Ruby, allowing\n non-blocking
48
- IO behaviour on the same thread\n as provided by EventMachine or
49
- Celluloid."
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: 1.8.25
101
+ rubygems_version: 2.0.6
107
102
  signing_key:
108
- specification_version: 3
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