activerecord-bogacs 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +17 -4
- data/lib/active_record/bogacs/default_pool.rb +56 -225
- data/lib/active_record/bogacs/false_pool.rb +2 -2
- data/lib/active_record/bogacs/pool_support.rb +44 -0
- data/lib/active_record/bogacs/version.rb +1 -1
- data/test/active_record/bogacs/default_pool_test.rb +2 -0
- data/test/active_record/bogacs/false_pool_test.rb +7 -6
- data/test/active_record/connection_pool_test_methods.rb +46 -0
- data/test/test_helper.rb +11 -3
- 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: b0aec44c1b08bd47f913dcce2eba41e1d30b1fa0
|
4
|
+
data.tar.gz: a506eb318972490b316604732aded93e5079e5d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc20088b6faeba8de52781af835d3cc078017bfcb7139b14e96d9f503fc3019340bbbe5fc0ae1ce8a000fb42a620a1fc3fda114b2dbe057f36d5e974ed892b28
|
7
|
+
data.tar.gz: 4600c5ed962dfb2682cc9f5911292442ac90951af19c3511d069b97175a5114f4c4f05de46bbfad25f5ed821c44388946b6336b84c4b636f08b498f57fae68b7
|
data/.travis.yml
CHANGED
@@ -22,7 +22,7 @@ script:
|
|
22
22
|
env:
|
23
23
|
- JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=mysql AR_VERSION="~> 4.1.9" HIKARI_VERSION="2.3.12"
|
24
24
|
- JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=postgresql AR_VERSION="~> 4.1.9" HIKARI_VERSION="2.3.2-java6"
|
25
|
-
- JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=mysql AR_VERSION="~> 4.1.
|
25
|
+
- JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=mysql AR_VERSION="~> 4.1.11" HIKARI_VERSION="2.0.1-java6"
|
26
26
|
- JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=postgresql AR_VERSION="~> 3.2.18" HIKARI_VERSION="1.4.0"
|
27
27
|
- JRUBY_OPTS="--1.8 $JRUBY_OPTS" AR_ADAPTER=mysql AR_VERSION="~> 3.2.18" HIKARI_VERSION="2.2.5-java6"
|
28
28
|
matrix:
|
@@ -36,15 +36,28 @@ matrix:
|
|
36
36
|
env: JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=postgresql AR_VERSION="~> 4.1.9" HIKARI_VERSION="2.3.2-java6"
|
37
37
|
jdk: oraclejdk8
|
38
38
|
- rvm: jruby-1.7.22
|
39
|
-
env: JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=mysql AR_VERSION="~> 4.1.
|
39
|
+
env: JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=mysql AR_VERSION="~> 4.1.13" HIKARI_VERSION="2.0.1-java6"
|
40
40
|
jdk: oraclejdk8
|
41
41
|
- rvm: jruby-1.7.22
|
42
42
|
env: JRUBY_OPTS="--1.8 $JRUBY_OPTS" AR_ADAPTER=mysql AR_VERSION="~> 3.2.18" HIKARI_VERSION="2.2.5-java6"
|
43
43
|
jdk: oraclejdk8
|
44
44
|
include:
|
45
45
|
- rvm: jruby-9.0.1.0
|
46
|
-
env: JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=mysql AR_VERSION="~> 4.1.
|
46
|
+
env: JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=mysql AR_VERSION="~> 4.1.13" HIKARI_VERSION="2.2.5-java6"
|
47
47
|
jdk: oraclejdk7
|
48
48
|
- rvm: jruby-9.0.1.0
|
49
49
|
env: JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=mysql AR_VERSION="~> 3.2.18" HIKARI_VERSION="2.3.9"
|
50
|
-
jdk: oraclejdk8
|
50
|
+
jdk: oraclejdk8
|
51
|
+
# AR 4.2
|
52
|
+
- rvm: jruby-1.7.22
|
53
|
+
env: JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=mysql AR_VERSION="~> 4.1.13" HIKARI_VERSION="2.2.5-java6"
|
54
|
+
jdk: oraclejdk7
|
55
|
+
- rvm: jruby-9.0.1.0
|
56
|
+
env: JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=mysql AR_VERSION="~> 4.2.4" HIKARI_VERSION="2.3.12"
|
57
|
+
jdk: oraclejdk8
|
58
|
+
- rvm: jruby-1.7.22
|
59
|
+
env: JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=postgresql AR_VERSION="~> 4.2.4" HIKARI_VERSION="2.2.5-java6"
|
60
|
+
jdk: oraclejdk8
|
61
|
+
- rvm: jruby-9.0.1.0
|
62
|
+
env: JRUBY_OPTS="$JRUBY_OPTS" AR_ADAPTER=postgresql AR_VERSION="~> 4.1.13" HIKARI_VERSION="2.3.12"
|
63
|
+
jdk: oraclejdk7
|
@@ -33,14 +33,16 @@ module ActiveRecord
|
|
33
33
|
# There are several connection-pooling-related options that you can add to
|
34
34
|
# your database connection configuration:
|
35
35
|
#
|
36
|
-
# *
|
37
|
-
# *
|
36
|
+
# * **pool**: number indicating size of connection pool (default 5)
|
37
|
+
# * **checkout_timeout**: number of seconds to block and wait for a connection
|
38
38
|
# before giving up and raising a timeout error (default 5 seconds).
|
39
|
-
# *
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
39
|
+
# * **pool_initial**: number of connections to pre-initialize when the pool
|
40
|
+
# is created (default 0).
|
41
|
+
# * **reaping_frequency**: frequency in seconds to periodically run a reaper,
|
42
|
+
# which attempts to find and close "dead" connections (can occur if a caller
|
43
|
+
# forgets to close a connection at the end of a thread or a thread dies unexpectedly)
|
44
|
+
# Default is `nil`, which means don't run the periodical Reaper at all (reaping
|
45
|
+
# will still happen occasionally).
|
44
46
|
class DefaultPool
|
45
47
|
# Threadsafe, fair, FIFO queue. Meant to be used by ConnectionPool
|
46
48
|
# with which it shares a Monitor. But could be a generic Queue.
|
@@ -158,7 +160,7 @@ module ActiveRecord
|
|
158
160
|
|
159
161
|
yield if block_given?
|
160
162
|
|
161
|
-
|
163
|
+
while true
|
162
164
|
@cond.wait(timeout - elapsed)
|
163
165
|
|
164
166
|
return remove if any?
|
@@ -227,8 +229,8 @@ module ActiveRecord
|
|
227
229
|
if spec.config[:pool]
|
228
230
|
@size = spec.config[:pool].to_i
|
229
231
|
else
|
230
|
-
if defined? Rails.env && Rails.env.
|
231
|
-
logger && logger.debug("pool: option not set, using
|
232
|
+
if defined? Rails.env && ( (! Rails.env.development? && ! Rails.env.test?) rescue nil )
|
233
|
+
logger && logger.debug("pool: option not set, using default size: 5")
|
232
234
|
end
|
233
235
|
@size = 5
|
234
236
|
end
|
@@ -253,6 +255,8 @@ module ActiveRecord
|
|
253
255
|
#
|
254
256
|
# #connection can be called any number of times; the connection is
|
255
257
|
# held in a hash keyed by the thread id.
|
258
|
+
#
|
259
|
+
# @return [ActiveRecord::ConnectionAdapters::AbstractAdapter]
|
256
260
|
def connection
|
257
261
|
connection_id = current_connection_id
|
258
262
|
unless conn = @reserved_connections.fetch(connection_id, nil)
|
@@ -264,6 +268,8 @@ module ActiveRecord
|
|
264
268
|
end
|
265
269
|
|
266
270
|
# Is there an open connection that is being used for the current thread?
|
271
|
+
#
|
272
|
+
# @return [true, false]
|
267
273
|
def active_connection?
|
268
274
|
connection_id = current_connection_id
|
269
275
|
if conn = @reserved_connections.fetch(connection_id, nil)
|
@@ -286,6 +292,8 @@ module ActiveRecord
|
|
286
292
|
# If a connection already exists yield it to the block. If no connection
|
287
293
|
# exists checkout a connection, yield it to the block, and checkin the
|
288
294
|
# connection when finished.
|
295
|
+
#
|
296
|
+
# @yield [ActiveRecord::ConnectionAdapters::AbstractAdapter]
|
289
297
|
def with_connection
|
290
298
|
connection_id = current_connection_id
|
291
299
|
fresh_connection = true unless active_connection?
|
@@ -295,6 +303,8 @@ module ActiveRecord
|
|
295
303
|
end
|
296
304
|
|
297
305
|
# Returns true if a connection has already been opened.
|
306
|
+
#
|
307
|
+
# @return [true, false]
|
298
308
|
def connected?
|
299
309
|
@connections.size > 0 # synchronize { @connections.any? }
|
300
310
|
end
|
@@ -344,6 +354,7 @@ module ActiveRecord
|
|
344
354
|
|
345
355
|
# Return any checked-out connections back to the pool by threads that
|
346
356
|
# are no longer alive.
|
357
|
+
# @private AR 3.2 compatibility
|
347
358
|
def clear_stale_cached_connections!
|
348
359
|
keys = Thread.list.find_all { |t| t.alive? }.map(&:object_id)
|
349
360
|
keys = @reserved_connections.keys - keys
|
@@ -354,60 +365,58 @@ module ActiveRecord
|
|
354
365
|
end
|
355
366
|
end if ActiveRecord::VERSION::MAJOR < 4
|
356
367
|
|
357
|
-
# Check-out a database connection from the pool,
|
358
|
-
#
|
368
|
+
# Check-out a database connection from the pool, callers are expected to
|
369
|
+
# call #checkin when the connection is no longer needed, so that others
|
370
|
+
# can use it.
|
359
371
|
#
|
360
372
|
# This is done by either returning and leasing existing connection, or by
|
361
373
|
# creating a new connection and leasing it.
|
362
374
|
#
|
363
|
-
#
|
364
|
-
#
|
365
|
-
#
|
366
|
-
#
|
367
|
-
# Returns: an AbstractAdapter object.
|
368
|
-
#
|
369
|
-
# Raises:
|
370
|
-
# - ConnectionTimeoutError: no connection can be obtained from the pool.
|
375
|
+
# @return [ActiveRecord::ConnectionAdapters::AbstractAdapter]
|
376
|
+
# @raise [ActiveRecord::ConnectionTimeoutError] if all connections are leased
|
377
|
+
# and the pool is at capacity (meaning the number of currently leased
|
378
|
+
# connections is greater than or equal to the size limit set)
|
371
379
|
def checkout
|
380
|
+
conn = nil
|
372
381
|
synchronize do
|
373
382
|
conn = acquire_connection
|
374
383
|
conn.lease
|
375
|
-
checkout_and_verify(conn)
|
376
384
|
end
|
385
|
+
checkout_and_verify(conn)
|
377
386
|
end
|
378
387
|
|
379
|
-
# Check-in a database connection back into the pool
|
380
|
-
# no longer need this connection.
|
388
|
+
# Check-in a database connection back into the pool.
|
381
389
|
#
|
382
|
-
#
|
383
|
-
# calling
|
390
|
+
# @param [ActiveRecord::ConnectionAdapters::AbstractAdapter] connection
|
391
|
+
# object, which was obtained earlier by calling #checkout on this pool
|
392
|
+
# @see #checkout
|
384
393
|
def checkin(conn, released = nil)
|
385
394
|
synchronize do
|
386
|
-
conn
|
387
|
-
conn.expire
|
388
|
-
end
|
395
|
+
_run_checkin_callbacks(conn)
|
389
396
|
|
390
|
-
release conn.owner unless released
|
397
|
+
release conn, conn.owner unless released
|
391
398
|
|
392
399
|
@available.add conn
|
393
400
|
end
|
394
401
|
end
|
395
402
|
|
396
|
-
# Remove a connection from the connection pool. The connection
|
397
|
-
# remain open and active but will no longer be managed by this pool.
|
403
|
+
# Remove a connection from the connection pool. The returned connection
|
404
|
+
# will remain open and active but will no longer be managed by this pool.
|
405
|
+
#
|
406
|
+
# @return [ActiveRecord::ConnectionAdapters::AbstractAdapter]
|
398
407
|
def remove(conn)
|
399
408
|
synchronize do
|
400
409
|
@connections.delete conn
|
401
410
|
@available.delete conn
|
402
411
|
|
403
|
-
release conn.owner
|
412
|
+
release conn, conn.owner
|
404
413
|
|
405
414
|
@available.add checkout_new_connection if @available.any_waiting?
|
406
415
|
end
|
407
416
|
end
|
408
417
|
|
409
418
|
# Recover lost connections for the pool. A lost connection can occur if
|
410
|
-
# a
|
419
|
+
# a caller forgets to #checkin a connection for a given thread when its done
|
411
420
|
# or a thread dies unexpectedly.
|
412
421
|
def reap
|
413
422
|
stale_connections = synchronize do
|
@@ -449,25 +458,25 @@ module ActiveRecord
|
|
449
458
|
end
|
450
459
|
end
|
451
460
|
|
452
|
-
def release(owner)
|
461
|
+
def release(conn, owner)
|
453
462
|
thread_id = owner.object_id
|
454
|
-
@reserved_connections
|
463
|
+
if @reserved_connections[thread_id] == conn
|
464
|
+
@reserved_connections.delete thread_id
|
465
|
+
end
|
455
466
|
end
|
456
467
|
|
457
468
|
def checkout_new_connection
|
458
469
|
raise ConnectionNotEstablished unless @automatic_reconnect
|
459
470
|
|
460
|
-
|
461
|
-
|
462
|
-
@connections <<
|
463
|
-
|
471
|
+
conn = new_connection
|
472
|
+
conn.pool = self
|
473
|
+
@connections << conn
|
474
|
+
conn
|
464
475
|
end
|
465
476
|
|
466
|
-
def checkout_and_verify(
|
467
|
-
|
468
|
-
|
469
|
-
end
|
470
|
-
c
|
477
|
+
def checkout_and_verify(conn)
|
478
|
+
_run_checkout_callbacks(conn)
|
479
|
+
conn
|
471
480
|
end
|
472
481
|
|
473
482
|
def prefill_initial_connections
|
@@ -481,189 +490,11 @@ module ActiveRecord
|
|
481
490
|
conns
|
482
491
|
end
|
483
492
|
|
484
|
-
|
485
|
-
|
486
|
-
end
|
487
|
-
|
488
|
-
end
|
489
|
-
|
490
|
-
=begin
|
491
|
-
|
492
|
-
# ConnectionHandler is a collection of ConnectionPool objects. It is used
|
493
|
-
# for keeping separate connection pools for Active Record models that connect
|
494
|
-
# to different databases.
|
495
|
-
#
|
496
|
-
# For example, suppose that you have 5 models, with the following hierarchy:
|
497
|
-
#
|
498
|
-
# |
|
499
|
-
# +-- Book
|
500
|
-
# | |
|
501
|
-
# | +-- ScaryBook
|
502
|
-
# | +-- GoodBook
|
503
|
-
# +-- Author
|
504
|
-
# +-- BankAccount
|
505
|
-
#
|
506
|
-
# Suppose that Book is to connect to a separate database (i.e. one other
|
507
|
-
# than the default database). Then Book, ScaryBook and GoodBook will all use
|
508
|
-
# the same connection pool. Likewise, Author and BankAccount will use the
|
509
|
-
# same connection pool. However, the connection pool used by Author/BankAccount
|
510
|
-
# is not the same as the one used by Book/ScaryBook/GoodBook.
|
511
|
-
#
|
512
|
-
# Normally there is only a single ConnectionHandler instance, accessible via
|
513
|
-
# ActiveRecord::Base.connection_handler. Active Record models use this to
|
514
|
-
# determine the connection pool that they should use.
|
515
|
-
class ConnectionHandler
|
516
|
-
def initialize
|
517
|
-
# These caches are keyed by klass.name, NOT klass. Keying them by klass
|
518
|
-
# alone would lead to memory leaks in development mode as all previous
|
519
|
-
# instances of the class would stay in memory.
|
520
|
-
@owner_to_pool = ThreadSafe::Cache.new(:initial_capacity => 2) do |h,k|
|
521
|
-
h[k] = ThreadSafe::Cache.new(:initial_capacity => 2)
|
522
|
-
end
|
523
|
-
@class_to_pool = ThreadSafe::Cache.new(:initial_capacity => 2) do |h,k|
|
524
|
-
h[k] = ThreadSafe::Cache.new
|
525
|
-
end
|
526
|
-
end
|
527
|
-
|
528
|
-
def connection_pool_list
|
529
|
-
owner_to_pool.values.compact
|
530
|
-
end
|
531
|
-
|
532
|
-
def connection_pools
|
533
|
-
ActiveSupport::Deprecation.warn(
|
534
|
-
"In the next release, this will return the same as #connection_pool_list. " \
|
535
|
-
"(An array of pools, rather than a hash mapping specs to pools.)"
|
536
|
-
)
|
537
|
-
Hash[connection_pool_list.map { |pool| [pool.spec, pool] }]
|
538
|
-
end
|
539
|
-
|
540
|
-
def establish_connection(owner, spec)
|
541
|
-
@class_to_pool.clear
|
542
|
-
raise RuntimeError, "Anonymous class is not allowed." unless owner.name
|
543
|
-
owner_to_pool[owner.name] = ConnectionAdapters::ConnectionPool.new(spec)
|
544
|
-
end
|
545
|
-
|
546
|
-
# Returns true if there are any active connections among the connection
|
547
|
-
# pools that the ConnectionHandler is managing.
|
548
|
-
def active_connections?
|
549
|
-
connection_pool_list.any?(&:active_connection?)
|
550
|
-
end
|
551
|
-
|
552
|
-
# Returns any connections in use by the current thread back to the pool,
|
553
|
-
# and also returns connections to the pool cached by threads that are no
|
554
|
-
# longer alive.
|
555
|
-
def clear_active_connections!
|
556
|
-
connection_pool_list.each(&:release_connection)
|
557
|
-
end
|
558
|
-
|
559
|
-
# Clears the cache which maps classes.
|
560
|
-
def clear_reloadable_connections!
|
561
|
-
connection_pool_list.each(&:clear_reloadable_connections!)
|
562
|
-
end
|
563
|
-
|
564
|
-
def clear_all_connections!
|
565
|
-
connection_pool_list.each(&:disconnect!)
|
566
|
-
end
|
493
|
+
#@@logger = nil
|
494
|
+
def logger; ::ActiveRecord::Base.logger end
|
495
|
+
#def logger=(logger); @@logger = logger end
|
567
496
|
|
568
|
-
# Locate the connection of the nearest super class. This can be an
|
569
|
-
# active or defined connection: if it is the latter, it will be
|
570
|
-
# opened and set as the active connection for the class it was defined
|
571
|
-
# for (not necessarily the current class).
|
572
|
-
def retrieve_connection(klass) #:nodoc:
|
573
|
-
pool = retrieve_connection_pool(klass)
|
574
|
-
(pool && pool.connection) or raise ConnectionNotEstablished
|
575
|
-
end
|
576
|
-
|
577
|
-
# Returns true if a connection that's accessible to this class has
|
578
|
-
# already been opened.
|
579
|
-
def connected?(klass)
|
580
|
-
conn = retrieve_connection_pool(klass)
|
581
|
-
conn && conn.connected?
|
582
|
-
end
|
583
|
-
|
584
|
-
# Remove the connection for this class. This will close the active
|
585
|
-
# connection and the defined connection (if they exist). The result
|
586
|
-
# can be used as an argument for establish_connection, for easily
|
587
|
-
# re-establishing the connection.
|
588
|
-
def remove_connection(owner)
|
589
|
-
if pool = owner_to_pool.delete(owner.name)
|
590
|
-
@class_to_pool.clear
|
591
|
-
pool.automatic_reconnect = false
|
592
|
-
pool.disconnect!
|
593
|
-
pool.spec.config
|
594
|
-
end
|
595
|
-
end
|
596
|
-
|
597
|
-
# Retrieving the connection pool happens a lot so we cache it in @class_to_pool.
|
598
|
-
# This makes retrieving the connection pool O(1) once the process is warm.
|
599
|
-
# When a connection is established or removed, we invalidate the cache.
|
600
|
-
#
|
601
|
-
# Ideally we would use #fetch here, as class_to_pool[klass] may sometimes be nil.
|
602
|
-
# However, benchmarking (https://gist.github.com/jonleighton/3552829) showed that
|
603
|
-
# #fetch is significantly slower than #[]. So in the nil case, no caching will
|
604
|
-
# take place, but that's ok since the nil case is not the common one that we wish
|
605
|
-
# to optimise for.
|
606
|
-
def retrieve_connection_pool(klass)
|
607
|
-
class_to_pool[klass.name] ||= begin
|
608
|
-
until pool = pool_for(klass)
|
609
|
-
klass = klass.superclass
|
610
|
-
break unless klass <= Base
|
611
|
-
end
|
612
|
-
|
613
|
-
class_to_pool[klass.name] = pool
|
614
|
-
end
|
615
|
-
end
|
616
|
-
|
617
|
-
private
|
618
|
-
|
619
|
-
def owner_to_pool
|
620
|
-
@owner_to_pool[Process.pid]
|
621
|
-
end
|
622
|
-
|
623
|
-
def class_to_pool
|
624
|
-
@class_to_pool[Process.pid]
|
625
|
-
end
|
626
|
-
|
627
|
-
def pool_for(owner)
|
628
|
-
owner_to_pool.fetch(owner.name) {
|
629
|
-
if ancestor_pool = pool_from_any_process_for(owner)
|
630
|
-
# A connection was established in an ancestor process that must have
|
631
|
-
# subsequently forked. We can't reuse the connection, but we can copy
|
632
|
-
# the specification and establish a new connection with it.
|
633
|
-
establish_connection owner, ancestor_pool.spec
|
634
|
-
else
|
635
|
-
owner_to_pool[owner.name] = nil
|
636
|
-
end
|
637
|
-
}
|
638
|
-
end
|
639
|
-
|
640
|
-
def pool_from_any_process_for(owner)
|
641
|
-
owner_to_pool = @owner_to_pool.values.find { |v| v[owner.name] }
|
642
|
-
owner_to_pool && owner_to_pool[owner.name]
|
643
|
-
end
|
644
497
|
end
|
645
498
|
|
646
|
-
class ConnectionManagement
|
647
|
-
def initialize(app)
|
648
|
-
@app = app
|
649
|
-
end
|
650
|
-
|
651
|
-
def call(env)
|
652
|
-
testing = env.key?('rack.test')
|
653
|
-
|
654
|
-
response = @app.call(env)
|
655
|
-
response[2] = ::Rack::BodyProxy.new(response[2]) do
|
656
|
-
ActiveRecord::Base.clear_active_connections! unless testing
|
657
|
-
end
|
658
|
-
|
659
|
-
response
|
660
|
-
rescue Exception
|
661
|
-
ActiveRecord::Base.clear_active_connections! unless testing
|
662
|
-
raise
|
663
|
-
end
|
664
|
-
end
|
665
|
-
|
666
|
-
=end
|
667
|
-
|
668
499
|
end
|
669
500
|
end
|
@@ -144,7 +144,7 @@ module ActiveRecord
|
|
144
144
|
#synchronize do
|
145
145
|
conn = checkout_new_connection # acquire_connection
|
146
146
|
conn.lease
|
147
|
-
conn
|
147
|
+
_run_checkout_callbacks(conn) # checkout_and_verify(conn)
|
148
148
|
conn
|
149
149
|
#end
|
150
150
|
end
|
@@ -157,7 +157,7 @@ module ActiveRecord
|
|
157
157
|
def checkin(conn, do_release = true)
|
158
158
|
release(conn) if do_release
|
159
159
|
#synchronize do
|
160
|
-
conn
|
160
|
+
_run_checkin_callbacks(conn)
|
161
161
|
#release conn
|
162
162
|
#@available.add conn
|
163
163
|
#end
|
@@ -36,6 +36,50 @@ module ActiveRecord
|
|
36
36
|
end
|
37
37
|
end if ActiveRecord::VERSION::MAJOR < 4
|
38
38
|
|
39
|
+
private
|
40
|
+
|
41
|
+
if ActiveRecord::VERSION::STRING > '4.2'
|
42
|
+
|
43
|
+
def _run_checkin_callbacks(conn)
|
44
|
+
if conn.respond_to?(:_run_checkin_callbacks)
|
45
|
+
conn._run_checkin_callbacks do
|
46
|
+
conn.expire
|
47
|
+
end
|
48
|
+
else
|
49
|
+
conn.run_callbacks :checkin do
|
50
|
+
conn.expire
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def _run_checkout_callbacks(conn)
|
56
|
+
if conn.respond_to?(:_run_checkout_callbacks)
|
57
|
+
conn._run_checkout_callbacks do
|
58
|
+
conn.verify!
|
59
|
+
end
|
60
|
+
else
|
61
|
+
conn.run_callbacks :checkout do
|
62
|
+
conn.verify!
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
else
|
68
|
+
|
69
|
+
def _run_checkin_callbacks(conn)
|
70
|
+
conn.run_callbacks :checkin do
|
71
|
+
conn.expire
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def _run_checkout_callbacks(conn)
|
76
|
+
conn.run_callbacks :checkout do
|
77
|
+
conn.verify!
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
39
83
|
end
|
40
84
|
end
|
41
85
|
end
|
@@ -12,8 +12,6 @@ module ActiveRecord
|
|
12
12
|
# extend Bogacs::TestHelper
|
13
13
|
extend Bogacs::JndiTestHelper
|
14
14
|
|
15
|
-
@@data_source = nil
|
16
|
-
|
17
15
|
def self.startup
|
18
16
|
return if self == TestBase
|
19
17
|
|
@@ -25,7 +23,11 @@ module ActiveRecord
|
|
25
23
|
def self.shutdown
|
26
24
|
return if self == TestBase
|
27
25
|
|
28
|
-
|
26
|
+
begin
|
27
|
+
close_data_source
|
28
|
+
ensure
|
29
|
+
@@data_source = nil
|
30
|
+
end
|
29
31
|
|
30
32
|
ActiveRecord::Base.connection_pool.disconnect!
|
31
33
|
ConnectionAdapters::ConnectionHandler.connection_pool_class = ConnectionAdapters::ConnectionPool
|
@@ -46,6 +48,8 @@ module ActiveRecord
|
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
51
|
+
@@data_source = nil
|
52
|
+
|
49
53
|
def self.init_data_source
|
50
54
|
setup_jdbc_context
|
51
55
|
bind_data_source @@data_source = build_data_source(raw_config)
|
@@ -343,9 +347,6 @@ module ActiveRecord
|
|
343
347
|
com.zaxxer.hikari.HikariDataSource.class_eval do
|
344
348
|
field_reader :pool unless method_defined? :pool
|
345
349
|
end
|
346
|
-
com.zaxxer.hikari.pool.HikariPool.class_eval do
|
347
|
-
field_reader :isShutdown unless method_defined? :isShutdown
|
348
|
-
end
|
349
350
|
|
350
351
|
data_source
|
351
352
|
end
|
@@ -329,6 +329,52 @@ module ActiveRecord
|
|
329
329
|
# assert_raises { handler.establish_connection anonymous, nil }
|
330
330
|
#end
|
331
331
|
|
332
|
+
def test_pooled_connection_remove
|
333
|
+
# ActiveRecord::Base.establish_connection(@connection.merge({:pool => 2, :checkout_timeout => 0.5}))
|
334
|
+
@pool.instance_variable_set(:@size, 2)
|
335
|
+
# old_connection = ActiveRecord::Base.connection
|
336
|
+
old_connection = @pool.connection
|
337
|
+
# extra_connection = ActiveRecord::Base.connection_pool.checkout
|
338
|
+
extra_connection = @pool.checkout
|
339
|
+
# ActiveRecord::Base.connection_pool.remove(extra_connection)
|
340
|
+
@pool.remove(extra_connection)
|
341
|
+
# assert_equal ActiveRecord::Base.connection, old_connection
|
342
|
+
assert_equal @pool.connection, old_connection
|
343
|
+
end
|
344
|
+
|
345
|
+
def test_pooled_connection_checkin_two
|
346
|
+
checkout_checkin_connections_loop 2, 3
|
347
|
+
assert_equal 3, @connection_count
|
348
|
+
assert_equal 0, @timed_out
|
349
|
+
# assert_equal 2, ActiveRecord::Base.connection_pool.connections.size
|
350
|
+
assert_equal 2, @pool.connections.size
|
351
|
+
end
|
352
|
+
|
353
|
+
protected
|
354
|
+
|
355
|
+
def checkout_checkin_connections_loop(pool_size, loops)
|
356
|
+
# ActiveRecord::Base.establish_connection(@connection.merge({:pool => pool_size, :checkout_timeout => 0.5}))
|
357
|
+
@pool.instance_variable_set(:@size, pool_size)
|
358
|
+
@pool.instance_variable_set(:@checkout_timeout, 0.5)
|
359
|
+
|
360
|
+
@connection_count = 0; @timed_out = 0
|
361
|
+
loops.times do
|
362
|
+
begin
|
363
|
+
# conn = ActiveRecord::Base.connection_pool.checkout
|
364
|
+
conn = @pool.checkout
|
365
|
+
# ActiveRecord::Base.connection_pool.checkin conn
|
366
|
+
@pool.checkin conn
|
367
|
+
|
368
|
+
@connection_count += 1
|
369
|
+
|
370
|
+
# ActiveRecord::Base.connection.tables
|
371
|
+
@pool.connection.tables
|
372
|
+
rescue ActiveRecord::ConnectionTimeoutError
|
373
|
+
@timed_out += 1
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
332
378
|
private
|
333
379
|
|
334
380
|
def active_connections(pool = self.pool)
|
data/test/test_helper.rb
CHANGED
@@ -349,7 +349,7 @@ module ActiveRecord
|
|
349
349
|
|
350
350
|
if ar_jdbc_config[:properties]
|
351
351
|
properties = java.util.Properties.new
|
352
|
-
|
352
|
+
ar_jdbc_config[:properties].each { |key, val| properties.put key.to_s, val.to_s }
|
353
353
|
data_source.setProperties properties
|
354
354
|
end
|
355
355
|
# JDBC pool tunings (some mapped from AR configuration) :
|
@@ -371,7 +371,15 @@ module ActiveRecord
|
|
371
371
|
|
372
372
|
|
373
373
|
def build_hikari_data_source(ar_jdbc_config = AR_CONFIG)
|
374
|
-
Dir.glob('test/jars/
|
374
|
+
unless hikari_jar = Dir.glob('test/jars/HikariCP*.jar').last
|
375
|
+
raise 'HikariCP jar not found in test/jars directory'
|
376
|
+
end
|
377
|
+
if ( version = File.basename(hikari_jar, '.jar').match(/\-([\w\.\-]$)/) ) && version[1] < '2.3.9'
|
378
|
+
Dir.glob('test/jars/{javassist,slf4j}*.jar').each { |jar| require jar }
|
379
|
+
else
|
380
|
+
Dir.glob('test/jars/{slf4j}*.jar').each { |jar| require jar }
|
381
|
+
end
|
382
|
+
require hikari_jar
|
375
383
|
|
376
384
|
configure_hikari_data_source(ar_jdbc_config)
|
377
385
|
end
|
@@ -400,7 +408,7 @@ module ActiveRecord
|
|
400
408
|
hikari_config.setDataSourceClassName 'org.postgresql.ds.PGSimpleDataSource'
|
401
409
|
hikari_config.addDataSourceProperty 'serverName', ar_jdbc_config[:host] || 'localhost'
|
402
410
|
hikari_config.addDataSourceProperty 'databaseName', ar_jdbc_config[:database]
|
403
|
-
hikari_config.addDataSourceProperty '
|
411
|
+
hikari_config.addDataSourceProperty 'portNumber', ar_jdbc_config[:port] if ar_jdbc_config[:port]
|
404
412
|
if ar_jdbc_config[:username]
|
405
413
|
hikari_config.addDataSourceProperty 'user', ar_jdbc_config[:username]
|
406
414
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-bogacs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karol Bucek
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|