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
+