Skip to content

Commit 462b0ea

Browse files
committed
- kgio based sockets
- specs for sockets - ConnectionPool, Mutex, ConditionVariable, Mysql2, ZMQ - Many fixes & improvements - ActiveRecord doesn't work yet :(
1 parent e95d859 commit 462b0ea

24 files changed

+1607
-101
lines changed

Gemfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@ source "http://rubygems.org"
22

33
gem "eventmachine", "= 1.0.0.beta.4"
44
gem "em-http-request"
5+
gem "ffi-rzmq"
6+
gem "mysql2"
57
gem "unicorn"
8+
gem "activerecord"
69

710
group :test do
811
gem "rr"
912
gem "minitest"
1013
gem "debugger"
14+
gem "minitest-reporters"
1115
end
1216

1317
gemspec

Gemfile.lock

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,26 @@ PATH
22
remote: .
33
specs:
44
green (0.0.1)
5+
kgio (= 2.7.4)
56

67
GEM
78
remote: http://rubygems.org/
89
specs:
10+
activemodel (3.2.3)
11+
activesupport (= 3.2.3)
12+
builder (~> 3.0.0)
13+
activerecord (3.2.3)
14+
activemodel (= 3.2.3)
15+
activesupport (= 3.2.3)
16+
arel (~> 3.0.2)
17+
tzinfo (~> 0.3.29)
18+
activesupport (3.2.3)
19+
i18n (~> 0.6)
20+
multi_json (~> 1.0)
921
addressable (2.2.8)
22+
ansi (1.4.2)
23+
arel (3.0.2)
24+
builder (3.0.0)
1025
columnize (0.3.5)
1126
cookiejar (0.3.0)
1227
debugger (1.1.3)
@@ -25,12 +40,25 @@ GEM
2540
em-socksify (0.2.0)
2641
eventmachine (>= 1.0.0.beta.4)
2742
eventmachine (1.0.0.beta.4)
43+
ffi (1.0.11)
44+
ffi-rzmq (0.9.3)
45+
ffi
2846
http_parser.rb (0.5.3)
47+
i18n (0.6.0)
2948
kgio (2.7.4)
3049
minitest (3.0.0)
50+
minitest-reporters (0.7.1)
51+
ansi
52+
builder
53+
minitest (>= 2.0, < 4.0)
54+
ruby-progressbar
55+
multi_json (1.3.6)
56+
mysql2 (0.3.11)
3157
rack (1.4.1)
3258
raindrops (0.8.0)
3359
rr (1.0.4)
60+
ruby-progressbar (0.0.10)
61+
tzinfo (0.3.33)
3462
unicorn (4.3.1)
3563
kgio (~> 2.6)
3664
rack
@@ -40,10 +68,14 @@ PLATFORMS
4068
ruby
4169

4270
DEPENDENCIES
71+
activerecord
4372
debugger
4473
em-http-request
4574
eventmachine (= 1.0.0.beta.4)
75+
ffi-rzmq
4676
green!
4777
minitest
78+
minitest-reporters
79+
mysql2
4880
rr
4981
unicorn

green.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
2020
s.rdoc_options = ["--charset=UTF-8"]
2121
s.extra_rdoc_files = %w[README.md]
2222

23-
23+
s.add_runtime_dependency("kgio", "2.7.4")
2424
# = MANIFEST =
2525
s.files = %w[
2626
Gemfile
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# AR adapter for using a green mysql2 connection
2+
# Just update your database.yml's adapter to be 'green_mysql2'
3+
4+
require 'green/mysql2'
5+
require 'green/activerecord'
6+
require 'active_record/connection_adapters/mysql2_adapter'
7+
8+
# module ActiveRecord
9+
# class Base
10+
# def self.green_mysql2_connection(config)
11+
# client = Green::ActiveRecord::ConnectionPool.new(size: config[:pool]) do
12+
# conn = ActiveRecord::ConnectionAdapters::GreenMysql2Adapter::Client.new(config.symbolize_keys)
13+
# # From Mysql2Adapter#configure_connection
14+
# conn.query_options.merge!(:as => :array)
15+
16+
# # By default, MySQL 'where id is null' selects the last inserted id.
17+
# # Turn this off. http://dev.rubyonrails.org/ticket/6778
18+
# variable_assignments = ['SQL_AUTO_IS_NULL=0']
19+
# encoding = config[:encoding]
20+
# variable_assignments << "NAMES '#{encoding}'" if encoding
21+
22+
# wait_timeout = config[:wait_timeout]
23+
# wait_timeout = 2592000 unless wait_timeout.is_a?(Fixnum)
24+
# variable_assignments << "@@wait_timeout = #{wait_timeout}"
25+
26+
# conn.query("SET #{variable_assignments.join(', ')}")
27+
# conn
28+
# end
29+
# options = [config[:host], config[:username], config[:password], config[:database], config[:port], config[:socket], 0]
30+
# ActiveRecord::ConnectionAdapters::GreenMysql2Adapter.new(client, logger, options, config)
31+
# end
32+
# end
33+
34+
# module ConnectionAdapters
35+
# class GreenMysql2Adapter < ::ActiveRecord::ConnectionAdapters::Mysql2Adapter
36+
37+
# class Column < AbstractMysqlAdapter::Column # :nodoc:
38+
# def adapter
39+
# GreenMysql2Adapter
40+
# end
41+
# end
42+
43+
# ADAPTER_NAME = 'GreenMysql2'
44+
45+
# class Client < Green::Mysql2::Client
46+
# include Green::ActiveRecord::Client
47+
# end
48+
49+
# include Green::ActiveRecord::Adapter
50+
51+
# def connect
52+
53+
# end
54+
# end
55+
# end
56+
# end
57+
58+
59+
60+
module ActiveRecord
61+
class Base
62+
def self.green_mysql2_connection(config)
63+
config[:username] = 'root' if config[:username].nil?
64+
65+
if Mysql2::Client.const_defined? :FOUND_ROWS
66+
config[:flags] = Mysql2::Client::FOUND_ROWS
67+
end
68+
69+
client = Green::Mysql2::Client.new(config.symbolize_keys)
70+
options = [config[:host], config[:username], config[:password], config[:database], config[:port], config[:socket], 0]
71+
ConnectionAdapters::GreenMysql2Adapter.new(client, logger, options, config)
72+
end
73+
end
74+
75+
module ConnectionAdapters
76+
class GreenMysql2Adapter < ::ActiveRecord::ConnectionAdapters::Mysql2Adapter
77+
78+
class Column < AbstractMysqlAdapter::Column # :nodoc:
79+
def adapter
80+
GreenMysql2Adapter
81+
end
82+
end
83+
84+
ADAPTER_NAME = 'GreenMysql2'
85+
86+
def connect
87+
@connection = Green::Mysql2::Client.new(@config)
88+
configure_connection
89+
end
90+
end
91+
end
92+
end

lib/green.rb

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,39 @@
44

55
class Green
66
VERSION = "0.0.1"
7+
8+
module GreenMethods
9+
def switch(*args)
10+
f.transfer(*args).tap do |*res|
11+
if res.size == 1 && res.first.is_a?(ThrowException)
12+
raise(res.first.exc)
13+
end
14+
end
15+
end
16+
17+
def throw(exc = RuntimeException.new)
18+
Green.hub.callback { switch(ThrowException.new exc) }
19+
end
20+
21+
def kill
22+
self.throw(GreenKill.new)
23+
end
24+
25+
def locals
26+
f.local_fiber_variables
27+
end
28+
29+
def [](name)
30+
locals[name]
31+
end
32+
33+
def []=(name, val)
34+
locals[name] = val
35+
end
36+
end
37+
738
class Proxy
39+
include GreenMethods
840
attr_reader :f
941
def initialize
1042
@f = Fiber.current
@@ -13,6 +45,10 @@ def initialize
1345
def switch(*args)
1446
f.transfer(*args)
1547
end
48+
49+
def alive?
50+
f.alive?
51+
end
1652
end
1753

1854
class SocketWaiter
@@ -89,42 +125,51 @@ def timeout(n, &blk)
89125
end
90126
end
91127

92-
# class GreenError < StandardError; end
93-
# class GreenKill < GreenError; end
128+
class GreenError < StandardError; end
129+
class GreenKill < GreenError; end
130+
131+
class ThrowException < Struct.new(:exc); end
94132

95133
require 'green/ext'
96134
require 'green/hub'
97135

98136
require 'green/hub/em'
99137

138+
include GreenMethods
139+
100140
attr_reader :f, :callbacks
101-
def initialize()
141+
def initialize
102142
@callbacks = []
143+
@alive = true
103144
@f = Fiber.new do
104-
res = yield
105-
@callbacks.each { |c| c.call(*res) }
145+
begin
146+
*res = yield
147+
rescue GreenKill => e
148+
end
149+
@alive = false
150+
@callbacks.each { |c|
151+
c.call(*res)
152+
}
106153
Green.hub.switch
107154
end
108155
@f[:green] = self
109156
end
110157

111-
112-
def switch(*args)
113-
f.transfer(*args).tap do |*res|
114-
res.size == 1 && res.first.is_a?(Exception) && raise(res.first)
115-
end
116-
end
117-
118-
def throw(exc = RuntimeException.new)
119-
switch(exc)
158+
def alive?
159+
@alive
120160
end
121161

122162
def start
123163
Green.hub.callback { self.switch }
124164
end
125165

126-
def callback(&blk)
127-
callbacks << blk
166+
def callback(cb=nil, &blk)
167+
cb ||= blk
168+
if alive?
169+
callbacks << cb
170+
else
171+
Green.hub.callback(cb)
172+
end
128173
end
129174

130175
def join
@@ -133,9 +178,5 @@ def join
133178
Green.hub.switch
134179
end
135180

136-
# def kill
137-
# self.throw(GreenKill.new)
138-
# end
139-
140181
MAIN = Fiber.current[:green] = Proxy.new
141182
end

0 commit comments

Comments
 (0)