michaelyta-neverblock-postgresql-adapter 0.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.
data/README
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Installation and Usage
|
2
|
+
======================
|
3
|
+
|
4
|
+
1. First, you need to get mysqlplus :
|
5
|
+
sudo gem install mysqlplus
|
6
|
+
|
7
|
+
2. Then, get the mysql neverblock adapter :
|
8
|
+
sudo gem install michaelyta-neverblock-postgresql-adapter -s http://gems.github.com
|
9
|
+
|
10
|
+
3. Finally, update config/database.yml :
|
11
|
+
production:
|
12
|
+
adapter: neverblock_postgresql
|
13
|
+
database: myapp_production
|
14
|
+
username: root
|
15
|
+
password:
|
16
|
+
host: localhost
|
17
|
+
pool: 6
|
18
|
+
|
19
|
+
And you are done, this will work seamlessly, no need to update any application code.
|
20
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Require original mysql adapter as we'll just extend it
|
2
|
+
require 'active_record/connection_adapters/postgresql_adapter'
|
3
|
+
require 'neverblock'
|
4
|
+
require 'fibered_postgresql_connection'
|
5
|
+
|
6
|
+
class ActiveRecord::ConnectionAdapters::NeverBlockPostgreSQLAdapter < ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
7
|
+
# Returns 'FiberedPostgreSQL' as adapter name for identification purposes.
|
8
|
+
def adapter_name
|
9
|
+
'NeverBlockPostgreSQL'
|
10
|
+
end
|
11
|
+
|
12
|
+
def connect
|
13
|
+
@connection = ::NB::DB::FiberedPostgresConnection.connect(*@connection_parameters[1..(@connection_parameters.length-1)])
|
14
|
+
end
|
15
|
+
|
16
|
+
# Close then reopen the connection.
|
17
|
+
def reconnect!
|
18
|
+
disconnect!
|
19
|
+
connect
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
class ActiveRecord::ConnectionAdapters::ConnectionPool
|
25
|
+
def current_connection_id #:nodoc:
|
26
|
+
NB::Fiber.current.object_id
|
27
|
+
end
|
28
|
+
|
29
|
+
def checkout
|
30
|
+
# Checkout an available connection
|
31
|
+
loop do
|
32
|
+
conn = if @checked_out.size < @connections.size
|
33
|
+
checkout_existing_connection
|
34
|
+
elsif @connections.size < @size
|
35
|
+
checkout_new_connection
|
36
|
+
end
|
37
|
+
return conn if conn
|
38
|
+
# No connections available; wait for one
|
39
|
+
@waiting ||= []
|
40
|
+
NB::Fiber.yield @waiting << NB::Fiber.current
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def checkin(conn)
|
45
|
+
conn.run_callbacks :checkin
|
46
|
+
@checked_out.delete conn
|
47
|
+
if @waiting && @waiting.size > 0
|
48
|
+
@waiting.shift.resume
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class ActiveRecord::Base
|
54
|
+
# Establishes a connection to the database that's used by all Active Record objects
|
55
|
+
def self.neverblock_postgresql_connection(config) # :nodoc:
|
56
|
+
config = config.symbolize_keys
|
57
|
+
host = config[:host]
|
58
|
+
port = config[:port] || 5432
|
59
|
+
username = config[:username].to_s
|
60
|
+
password = config[:password].to_s
|
61
|
+
size = config[:connections] || 4
|
62
|
+
|
63
|
+
if config.has_key?(:database)
|
64
|
+
database = config[:database]
|
65
|
+
else
|
66
|
+
raise ArgumentError, "No database specified. Missing argument: database."
|
67
|
+
end
|
68
|
+
|
69
|
+
# The postgres drivers don't allow the creation of an unconnected PGconn object,
|
70
|
+
# so just pass a nil connection object for the time being.
|
71
|
+
::ActiveRecord::ConnectionAdapters::NeverBlockPostgreSQLAdapter.new(nil, logger, [size, host, port, nil, nil, database, username, password], config)
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'pg'
|
2
|
+
|
3
|
+
module NeverBlock
|
4
|
+
|
5
|
+
module DB
|
6
|
+
|
7
|
+
# A modified postgres connection driver
|
8
|
+
# builds on the original pg driver.
|
9
|
+
# This driver is able to register the socket
|
10
|
+
# at a certain backend (Reacotr)
|
11
|
+
# and then whenever the query is executed
|
12
|
+
# within the scope of a friendly fiber (NB::Fiber)
|
13
|
+
# it will be done in async mode and the fiber
|
14
|
+
# will yield
|
15
|
+
class FiberedPostgresConnection < PGconn
|
16
|
+
|
17
|
+
# Assuming the use of NeverBlock fiber extensions and that the exec is run in
|
18
|
+
# the context of a fiber. One that have the value :neverblock set to true.
|
19
|
+
# All neverblock IO classes check this value, setting it to false will force
|
20
|
+
# the execution in a blocking way.
|
21
|
+
def exec(sql)
|
22
|
+
# TODO Still not "killing the query process"-proof
|
23
|
+
# In some cases, the query is simply sent but the fiber never yields
|
24
|
+
if NB.neverblocking? && NB.reactor.running?
|
25
|
+
send_query sql
|
26
|
+
while is_busy
|
27
|
+
NB.wait(:read, IO.new(socket))
|
28
|
+
consume_input
|
29
|
+
end
|
30
|
+
res, data = 0, []
|
31
|
+
while res != nil
|
32
|
+
res = self.get_result
|
33
|
+
data << res unless res.nil?
|
34
|
+
end
|
35
|
+
data.last
|
36
|
+
else
|
37
|
+
super(sql)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
alias_method :query, :exec
|
42
|
+
|
43
|
+
end #FiberedPostgresConnection
|
44
|
+
|
45
|
+
end #DB
|
46
|
+
|
47
|
+
end #NeverBlock
|
48
|
+
|
49
|
+
NeverBlock::DB::FPGConn = NeverBlock::DB::FiberedPostgresConnection
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "neverblock-postgresql-adapter"
|
3
|
+
s.version = "0.1"
|
4
|
+
s.date = "2009-07-19"
|
5
|
+
s.summary = "PostgreSQL Asyncronous AR connection adapter"
|
6
|
+
s.email = "oldmoe@gmail.com"
|
7
|
+
s.homepage = "http://github.com/michaelyta/neverblock-postgresql-adapter"
|
8
|
+
s.description = "A new postgresql asyncronous connection adapter for active_record using neverblock"
|
9
|
+
s.has_rdoc = false
|
10
|
+
s.authors = ["Muhammad A. Ali", "Michael Youssef"]
|
11
|
+
s.files = [
|
12
|
+
"neverblock-postgresql-adapter.gemspec",
|
13
|
+
"README",
|
14
|
+
"lib/active_record/connection_adapters/neverblock_postgresql_adapter.rb",
|
15
|
+
"lib/fibered_postgresql_connection.rb",
|
16
|
+
"test/active_record_postgresql_test.rb"
|
17
|
+
]
|
18
|
+
# s.rdoc_options = ["--main", "README"]
|
19
|
+
# s.extra_rdoc_files = ["README"]
|
20
|
+
s.add_dependency('neverblock', '>= 1.0')
|
21
|
+
s.add_dependency('mysqlplus', '>=0.1.1')
|
22
|
+
end
|
23
|
+
|
24
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'minitest/unit'
|
2
|
+
require 'neverblock'
|
3
|
+
require 'activerecord'
|
4
|
+
require '../lib/fibered_postgresql_connection'
|
5
|
+
|
6
|
+
class Book < ActiveRecord::Base
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
MiniTest::Unit.autorun
|
12
|
+
|
13
|
+
|
14
|
+
class ActiverecordTest < MiniTest::Unit::TestCase
|
15
|
+
def setup
|
16
|
+
super
|
17
|
+
ActiveRecord::Base.configurations = {
|
18
|
+
'test' => {
|
19
|
+
:adapter => 'neverblock_postgresql',
|
20
|
+
:username => 'postgres',
|
21
|
+
:password => 'postgres',
|
22
|
+
:encoding => 'utf8',
|
23
|
+
:database => 'postgres',
|
24
|
+
:pool => 8
|
25
|
+
}
|
26
|
+
}
|
27
|
+
ActiveRecord::Base.establish_connection 'test'
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_concurrency
|
31
|
+
count = 17
|
32
|
+
done = 0
|
33
|
+
t = Time.now
|
34
|
+
NB.reactor.run do
|
35
|
+
(1..count).each do
|
36
|
+
NB::Fiber.new do
|
37
|
+
Book.find_by_sql("select sleep(1) as sleep")
|
38
|
+
ActiveRecord::Base.connection_pool.release_connection
|
39
|
+
done += 1
|
40
|
+
puts done
|
41
|
+
if done == count
|
42
|
+
NB.reactor.stop
|
43
|
+
end
|
44
|
+
end.resume
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
assert_in_delta Time.now - t, 3, 1
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: michaelyta-neverblock-postgresql-adapter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Muhammad A. Ali
|
8
|
+
- Michael Youssef
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-07-19 00:00:00 -07:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: neverblock
|
18
|
+
type: :runtime
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "1.0"
|
25
|
+
version:
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: mysqlplus
|
28
|
+
type: :runtime
|
29
|
+
version_requirement:
|
30
|
+
version_requirements: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.1.1
|
35
|
+
version:
|
36
|
+
description: A new postgresql asyncronous connection adapter for active_record using neverblock
|
37
|
+
email: oldmoe@gmail.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- neverblock-postgresql-adapter.gemspec
|
46
|
+
- README
|
47
|
+
- lib/active_record/connection_adapters/neverblock_postgresql_adapter.rb
|
48
|
+
- lib/fibered_postgresql_connection.rb
|
49
|
+
- test/active_record_postgresql_test.rb
|
50
|
+
has_rdoc: false
|
51
|
+
homepage: http://github.com/michaelyta/neverblock-postgresql-adapter
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
version:
|
69
|
+
requirements: []
|
70
|
+
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.2.0
|
73
|
+
signing_key:
|
74
|
+
specification_version: 2
|
75
|
+
summary: PostgreSQL Asyncronous AR connection adapter
|
76
|
+
test_files: []
|
77
|
+
|