On Dec 2, 11:17 am, Jeremy Evans <[EMAIL PROTECTED]> wrote:
> The proper way to handle this would be to have the adapters raise a
> specific subclass of Sequel::DatabaseError when a database disconnect
> is detected, so that the connection pool code could rescue that error
> subclass and remove that connection from the connection pool and
> reraise the error (which the app can handle just like any other
> DatabaseError).  This requires a small change to the connection pool
> code as well as changes to adapters.  I think I'll give a shot at
> converting the built in reconnect support in the postgres adapter to
> this, and if that works, the approach can be expanded to the other
> adapters as other people decide to add support to them.

An initial shot at this proves fruitful:

$ ruby -I lib bin/sequel -E postgres:///sequel_test?user=_postgresql
I, [2008-12-02T12:28:14.350689 #26477]  INFO -- : SET
standard_conforming_strings = ON
I, [2008-12-02T12:28:14.351379 #26477]  INFO -- : SET DateStyle =
'ISO'
Your database is stored in DB...
irb(main):001:0> DB['SELECT 1'].all
I, [2008-12-02T12:28:18.716578 #26477]  INFO -- : SELECT 1
=> [{:"?column?"=>1}]
irb(main):002:0> DB.pool
=> #<Sequel::ConnectionPool:0x211e54968 @servers=[:default],
@sleep_time=0.001, @allocated={:default=>{}},
@disconnection_proc=#<Proc:[EMAIL PROTECTED]/lib/sequel_core/
database.rb:81>, @max_size=4, @available_connections={:default=>
[#<Sequel::Postgres::Adapter:0x211e543f0>]},
@convert_exceptions=false, @connection_proc=#<Proc:
[EMAIL PROTECTED]/lib/sequel_core/database.rb:80>, @timeout=5,
@mutex=#<Mutex:0x211e54918>, @created_count={:default=>1}>
irb(main):003:0> `sudo kill $(ps ax | fgrep postgres | fgrep
sequel_test | fgrep -v ruby | awk '{print $1}')`
=> ""
irb(main):004:0> DB['SELECT 1'].all
I, [2008-12-02T12:28:31.044393 #26477]  INFO -- : SELECT 1
FATAL:  terminating connection due to administrator command
I, [2008-12-02T12:28:31.044898 #26477]  INFO -- :
Sequel::DatabaseDisconnectError
Sequel::DatabaseDisconnectError: Sequel::DatabaseDisconnectError
        from ./lib/sequel_core/adapters/postgres.rb:141:in `execute'
        from ./lib/sequel_core/adapters/postgres.rb:236:in `execute'
        from ./lib/sequel_core/connection_pool.rb:109:in `hold'
        from ./lib/sequel_core/database.rb:362:in `synchronize'
        from ./lib/sequel_core/adapters/postgres.rb:236:in `execute'
        from ./lib/sequel_core/dataset.rb:464:in `execute'
        from ./lib/sequel_core/adapters/postgres.rb:314:in
`fetch_rows'
        from ./lib/sequel_core/dataset.rb:454:in `_each'
        from ./lib/sequel_core/dataset.rb:209:in `each'
        from ./lib/sequel_core/dataset.rb:148:in `all'
        from (irb):4
irb(main):005:0> DB.pool
=> #<Sequel::ConnectionPool:0x211e54968 @servers=[:default],
@sleep_time=0.001, @allocated={:default=>{}},
@disconnection_proc=#<Proc:[EMAIL PROTECTED]/lib/sequel_core/
database.rb:81>, @max_size=4, @available_connections={:default=>[]},
@convert_exceptions=false, @connection_proc=#<Proc:
[EMAIL PROTECTED]/lib/sequel_core/database.rb:80>, @timeout=5,
@mutex=#<Mutex:0x211e54918>, @created_count={:default=>0}>
irb(main):006:0> DB['SELECT 1'].all
I, [2008-12-02T12:28:43.204481 #26477]  INFO -- : SELECT 1
I, [2008-12-02T12:28:43.208265 #26477]  INFO -- : SET
standard_conforming_strings = ON
I, [2008-12-02T12:28:43.208725 #26477]  INFO -- : SET DateStyle =
'ISO'
=> [{:"?column?"=>1}]
irb(main):007:0> DB.pool
=> #<Sequel::ConnectionPool:0x211e54968 @servers=[:default],
@sleep_time=0.001, @allocated={:default=>{}},
@disconnection_proc=#<Proc:[EMAIL PROTECTED]/lib/sequel_core/
database.rb:81>, @max_size=4, @available_connections={:default=>
[#<Sequel::Postgres::Adapter:0x211d3e3f8>]},
@convert_exceptions=false, @connection_proc=#<Proc:
[EMAIL PROTECTED]/lib/sequel_core/database.rb:80>, @timeout=5,
@mutex=#<Mutex:0x211e54918>, @created_count={:default=>1}>

Don't be fooled by the logging, as it does send the SET commands
before the SELECT commands.

This change was more involved than I expected, but it wasn't too bad.
Because the connection should be disconnected when it is removed from
the pool, a disconnection_proc had to be added to the connection
pool.  This is because even if a disconnection is detected, there may
be some other cleanup needed (especially true for C-based adapters).
This is easy to set up generically, but the adapters are set up to
disconnect all connections at once, not just a single connection.  The
Database adapters need to be modified to add a disconnect_connection
method that accepts a single connection to disconnect.

While researching this, I think I fixed a bug in the connection pool
code that was added when master/slave/sharding support was added,
which was causing the wrong server to be used in the @created_count
hash.  This could have caused more than @max_connections connections
to be used.

I'm testing the patch right now, it should hopefully go in soon.

Jeremy
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sequel-talk?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to