green-em-pg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :test do
4
+ gem "sequel"
5
+ gem "minitest"
6
+ gem "minitest-reporters"
7
+ gem "debugger"
8
+ end
9
+
10
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,51 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ green-em-pg (0.1.0)
5
+ em-pg (>= 0.1)
6
+ eventmachine (>= 0.12)
7
+ green (>= 0.1.1)
8
+ pg (>= 0.14)
9
+
10
+ GEM
11
+ remote: http://rubygems.org/
12
+ specs:
13
+ ansi (1.4.3)
14
+ builder (3.1.4)
15
+ columnize (0.3.6)
16
+ debugger (1.3.0)
17
+ columnize (>= 0.3.1)
18
+ debugger-linecache (~> 1.1.1)
19
+ debugger-ruby_core_source (~> 1.1.7)
20
+ debugger-linecache (1.1.2)
21
+ debugger-ruby_core_source (>= 1.1.1)
22
+ debugger-ruby_core_source (1.1.7)
23
+ em-pg (0.1.1)
24
+ eventmachine (>= 0.12)
25
+ pg (>= 0.14)
26
+ eventmachine (1.0.0)
27
+ green (0.1.1)
28
+ kgio (= 2.7.4)
29
+ hashie (1.2.0)
30
+ kgio (2.7.4)
31
+ minitest (4.5.0)
32
+ minitest-reporters (0.14.7)
33
+ ansi
34
+ builder
35
+ minitest (>= 2.12, < 5.0)
36
+ powerbar
37
+ pg (0.14.1)
38
+ powerbar (1.0.11)
39
+ ansi (~> 1.4.0)
40
+ hashie (>= 1.1.0)
41
+ sequel (3.43.0)
42
+
43
+ PLATFORMS
44
+ ruby
45
+
46
+ DEPENDENCIES
47
+ debugger
48
+ green-em-pg!
49
+ minitest
50
+ minitest-reporters
51
+ sequel
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ green-em-pg
2
+ ===========
3
+
4
+ Simple wrapper around [em-pg](https://github.com/prepor/em-pg) for [Green](https://github.com/prepor/green). And [Sequel](http://sequel.rubyforge.org/) adapter.
5
+
6
+ Usage
7
+ -----
8
+
9
+ ```ruby
10
+ gem "green-em-pg"
11
+ ```
12
+
13
+ ```ruby
14
+ require "green-em/pg"
15
+
16
+ db = Green::EM::PG.new host: "localhost",
17
+ port: 5432,
18
+ dbname: "test",
19
+ user: "postgres",
20
+ password: "postgres"
21
+
22
+ res = db.send_qeury "select * from test"
23
+
24
+ puts res.inspect
25
+ ```
26
+
27
+ Sequel
28
+ ------
29
+
30
+ ```ruby
31
+ require "green-em/pg/sequal"
32
+ url = "postgres://postgres:postgres@localhost:5432/test"
33
+ db = Sequel.connect(url, pool_class: Green::EM::PG::Sequel::ConnectionPool)
34
+
35
+ puts db[:test].all.inspect
36
+ ```
data/Rakefile ADDED
@@ -0,0 +1,121 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'date'
4
+
5
+ #############################################################################
6
+ #
7
+ # Helper functions
8
+ #
9
+ #############################################################################
10
+
11
+ def name
12
+ @name ||= Dir['*.gemspec'].first.split('.').first
13
+ end
14
+
15
+ def version
16
+ line = File.read("lib/green-em/pg.rb")[/^\s*VERSION\s*=\s*.*/]
17
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
18
+ end
19
+
20
+ def date
21
+ Date.today.to_s
22
+ end
23
+
24
+ def rubyforge_project
25
+ name
26
+ end
27
+
28
+ def gemspec_file
29
+ "#{name}.gemspec"
30
+ end
31
+
32
+ def gem_file
33
+ "#{name}-#{version}.gem"
34
+ end
35
+
36
+ def replace_header(head, header_name)
37
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
38
+ end
39
+
40
+ #############################################################################
41
+ #
42
+ # Standard tasks
43
+ #
44
+ #############################################################################
45
+
46
+ task :default => :spec
47
+
48
+ require 'rake/testtask'
49
+ Rake::TestTask.new(:spec) do |test|
50
+ test.libs << 'lib' << 'spec'
51
+ test.pattern = 'spec/**/*_spec.rb'
52
+ test.verbose = true
53
+ end
54
+
55
+ desc "Open an irb session preloaded with this library"
56
+ task :console do
57
+ sh "irb -rubygems -r ./lib/#{name}.rb"
58
+ end
59
+
60
+ #############################################################################
61
+ #
62
+ # Custom tasks (add your own tasks here)
63
+ #
64
+ #############################################################################
65
+
66
+
67
+
68
+ #############################################################################
69
+ #
70
+ # Packaging tasks
71
+ #
72
+ #############################################################################
73
+
74
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
75
+ task :release => :build do
76
+ unless `git branch` =~ /^\* master$/
77
+ puts "You must be on the master branch to release!"
78
+ exit!
79
+ end
80
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
81
+ sh "git tag v#{version}"
82
+ sh "git push origin master"
83
+ sh "git push origin v#{version}"
84
+ sh "gem push pkg/#{name}-#{version}.gem"
85
+ end
86
+
87
+ desc "Build #{gem_file} into the pkg directory"
88
+ task :build => :gemspec do
89
+ sh "mkdir -p pkg"
90
+ sh "gem build #{gemspec_file}"
91
+ sh "mv #{gem_file} pkg"
92
+ end
93
+
94
+ desc "Generate #{gemspec_file}"
95
+ task :gemspec do
96
+ # read spec file and split out manifest section
97
+ spec = File.read(gemspec_file)
98
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
99
+
100
+ # replace name version and date
101
+ replace_header(head, :name)
102
+ replace_header(head, :version)
103
+ replace_header(head, :date)
104
+ #comment this out if your rubyforge_project has a different name
105
+ replace_header(head, :rubyforge_project)
106
+
107
+ # determine file list from git ls-files
108
+ files = `git ls-files`.
109
+ split("\n").
110
+ sort.
111
+ reject { |file| file =~ /^\./ }.
112
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
113
+ map { |file| " #{file}" }.
114
+ join("\n")
115
+
116
+ # piece file back together and write
117
+ manifest = " s.files = %w[\n#{files}\n ]\n"
118
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
119
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
120
+ puts "Updated #{gemspec_file}"
121
+ end
@@ -0,0 +1,30 @@
1
+ spec = Gem::Specification.new do |s|
2
+ s.name = 'green-em-pg'
3
+ s.version = '0.1.0'
4
+ s.date = '2013-01-28'
5
+ s.summary = 'Async PostgreSQL client API for Ruby/EventMachine'
6
+ s.email = "ceo@prepor.ru"
7
+ s.homepage = "http://github.com/prepor/em-postgres"
8
+ s.description = 'Async PostgreSQL client API for Ruby/EventMachine'
9
+ s.has_rdoc = false
10
+ s.authors = ["Andrew Rudenko"]
11
+ s.add_dependency('eventmachine', '>= 0.12')
12
+ s.add_dependency('pg', '>= 0.14')
13
+ s.add_dependency('green', '>= 0.1.1')
14
+ s.add_dependency('em-pg', '>= 0.1')
15
+
16
+ # = MANIFEST =
17
+ s.files = %w[
18
+ Gemfile
19
+ Gemfile.lock
20
+ README.md
21
+ Rakefile
22
+ green-em-pg.gemspec
23
+ lib/green-em/pg.rb
24
+ lib/green-em/pg/sequel.rb
25
+ spec/green-em/pg/sequel_spec.rb
26
+ spec/green-em/pg_spec.rb
27
+ spec/spec_helper.rb
28
+ ]
29
+ # = MANIFEST =
30
+ end
@@ -0,0 +1,24 @@
1
+ require 'green-em'
2
+ require 'em/pg'
3
+ class Green
4
+ module EM
5
+ class PG < ::EM::PG
6
+ VERSION = "0.1.0"
7
+ def self.new(*args)
8
+ Green.hub # ensure started green hub
9
+ db = allocate
10
+ db.instance_eval do
11
+ initialize(*args)
12
+ end
13
+ Green::EM.sync db
14
+ db
15
+ end
16
+
17
+ [:send_query, :send_prepare, :send_query_prepared, :send_describe_prepared, :send_describe_portal].each do |m|
18
+ define_method(m) do |*args|
19
+ Green::EM.sync super(*args)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,72 @@
1
+ require 'pg'
2
+ require 'forwardable'
3
+ require 'green-em/pg'
4
+ require 'sequel'
5
+ require 'green/connection_pool'
6
+ class Green
7
+ module EM
8
+ class PG
9
+ class Sequel
10
+ class ConnectionPool < ::Sequel::ConnectionPool
11
+ DEFAULT_SIZE = 4
12
+ attr_accessor :pool
13
+ def initialize(db, opts = {})
14
+ super
15
+ @pool = Green::ConnectionPool.new size: opts[:max_connection] || DEFAULT_SIZE,
16
+ disconnect_class: ::Sequel::DatabaseDisconnectError do
17
+ make_new(DEFAULT_SERVER)
18
+ end
19
+ end
20
+
21
+ def size
22
+ @pool.available.size
23
+ end
24
+
25
+ def hold(server = nil, &blk)
26
+ @pool.execute(&blk)
27
+ end
28
+
29
+ def disconnect(server = nil)
30
+ @pool.available.each{ |conn| db.disconnect_connection(conn) }
31
+ @pool.available.clear
32
+ end
33
+ end
34
+ end
35
+
36
+ class PGconn < Green::EM::PG
37
+ extend Forwardable
38
+
39
+ def_delegators :@pg, :status, :escape_string, :escape_bytea
40
+
41
+ class << self
42
+ alias :connect :new
43
+ end
44
+
45
+ { async_exec: :send_query,
46
+ prepare: :send_prepare,
47
+ exec_prepared: :send_query_prepared,
48
+ finish: :close }.each do |from, to|
49
+ define_method from do |*args|
50
+ send(to, *args)
51
+ end
52
+ end
53
+ # alias :async_exec :send_query
54
+ # alias :prepare :send_prepare
55
+ # alias :exec_prepared :send_query_prepared
56
+ # alias :finish :close
57
+
58
+ [:get_copy_data, :put_copy_data, :put_copy_end, :get_result, :wait_for_notify].each do |m|
59
+ define_method(m) do |*args|
60
+ raise "Unimplemented method #{m} in green postgres adapter"
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ PGconn = Green::EM::PG::PGconn
69
+
70
+ require 'sequel/adapters/postgres'
71
+
72
+ Sequel::Postgres::CONVERTED_EXCEPTIONS << ::EM::PG::Error
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+ require 'green-em/pg/sequel'
3
+ require 'green/group'
4
+
5
+ describe Green::EM::PG do
6
+ DELAY = 1
7
+ QUERY = "select pg_sleep(#{DELAY})"
8
+
9
+
10
+ let(:url) { DB_URL }
11
+ let(:size) { 1 }
12
+ let(:db) { Sequel.connect(url, max_connection: size, pool_class: Green::EM::PG::Sequel::ConnectionPool, db_logger: Logger.new(nil)) }
13
+ let(:test) { db[:test] }
14
+
15
+ before do
16
+ db.create_table!(:test) do
17
+ text :name
18
+ integer :value, index: true
19
+ end
20
+ end
21
+
22
+ after do
23
+ db.drop_table?(:test)
24
+ end
25
+
26
+ it "should connect and execute query" do
27
+ test.insert name: "andrew", value: 42
28
+ test.where(name: "andrew").first[:value].must_equal 42
29
+ end
30
+
31
+
32
+ describe "pool size is exceeded" do
33
+ let(:size) { 1 }
34
+ it "should queue requests" do
35
+ start = Time.now.to_f
36
+
37
+ g = Green::Group.new
38
+ res = []
39
+ g.spawn { res << db[QUERY].all }
40
+ g.spawn { res << db[QUERY].all }
41
+ g.join
42
+ (Time.now.to_f - start.to_f).must_be_within_delta DELAY * 2, DELAY * 2 * 0.15
43
+ res.size.must_equal 2
44
+ end
45
+ end
46
+
47
+ describe "pool size is enough" do
48
+ let(:size) { 2 }
49
+ it "should parallel requests" do
50
+ start = Time.now.to_f
51
+
52
+ g = Green::Group.new
53
+ res = []
54
+ g.spawn { res << db[QUERY].all }
55
+ g.spawn { res << db[QUERY].all }
56
+ g.join
57
+
58
+ (Time.now.to_f - start.to_f).must_be_within_delta DELAY, DELAY * 0.30
59
+ res.size.must_equal 2
60
+ end
61
+ end
62
+
63
+
64
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Green::EM::PG do
4
+ let(:db) { Green::EM::PG.new DB_CONFIG }
5
+ it "should execute query" do
6
+ res = db.send_query "select 1;"
7
+ res.first["?column?"].must_equal "1"
8
+ end
9
+ end
@@ -0,0 +1,26 @@
1
+ ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
2
+
3
+ ENV['GREEN_HUB'] = 'EM'
4
+ require 'bundler/setup'
5
+
6
+ require 'green-em/pg'
7
+
8
+ require 'minitest/spec'
9
+ require 'minitest/autorun'
10
+ require 'minitest/reporters'
11
+
12
+ logger = Logger.new nil
13
+
14
+ DB_CONFIG = {
15
+ host: "localhost",
16
+ port: 5432,
17
+ dbname: "test",
18
+ user: "postgres",
19
+ password: "postgres",
20
+ }
21
+
22
+ EM::PG.logger = logger
23
+
24
+ DB_URL = "postgres://%s:%s@%s:%d/%s" % [DB_CONFIG[:user], DB_CONFIG[:password], DB_CONFIG[:host], DB_CONFIG[:port], DB_CONFIG[:dbname]]
25
+
26
+ MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: green-em-pg
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Andrew Rudenko
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: eventmachine
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0.12'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0.12'
30
+ - !ruby/object:Gem::Dependency
31
+ name: pg
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0.14'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0.14'
46
+ - !ruby/object:Gem::Dependency
47
+ name: green
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.1.1
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.1.1
62
+ - !ruby/object:Gem::Dependency
63
+ name: em-pg
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0.1'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0.1'
78
+ description: Async PostgreSQL client API for Ruby/EventMachine
79
+ email: ceo@prepor.ru
80
+ executables: []
81
+ extensions: []
82
+ extra_rdoc_files: []
83
+ files:
84
+ - Gemfile
85
+ - Gemfile.lock
86
+ - README.md
87
+ - Rakefile
88
+ - green-em-pg.gemspec
89
+ - lib/green-em/pg.rb
90
+ - lib/green-em/pg/sequel.rb
91
+ - spec/green-em/pg/sequel_spec.rb
92
+ - spec/green-em/pg_spec.rb
93
+ - spec/spec_helper.rb
94
+ homepage: http://github.com/prepor/em-postgres
95
+ licenses: []
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 1.8.24
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: Async PostgreSQL client API for Ruby/EventMachine
118
+ test_files: []