michaelyta-neverblock-postgresql-adapter 0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+