oversip-mod-mysql 0.0.1 → 0.1.0
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.md +53 -119
- data/lib/oversip-mod-mysql.rb +25 -37
- data/lib/oversip-mod-mysql/version.rb +2 -2
- metadata +9 -13
- data/lib/oversip-mod-mysql/mysql2_em_client.rb +0 -8
data/README.md
CHANGED
@@ -1,167 +1,99 @@
|
|
1
1
|
# oversip-mod-mysql
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
Check the [mysql2 documentation](https://github.com/brianmario/mysql2/blob/master/README.md) for the exact syntax and usage of the MySQL queries.
|
3
|
+
## Overview
|
6
4
|
|
5
|
+
`oversip-mod-mysql` provides an easy to use MySQL connector for [OverSIP](http://www.oversip.net) proxy based on [mysql2](https://github.com/brianmario/mysql2) driver.
|
7
6
|
|
8
|
-
|
7
|
+
Starting from version 0.1.0 `oversip-mod-mysql` depends on [OverSIP](http://www.oversip.net) >= 1.3.0 which enforces the usage of "sync" style coding via [em-synchrony](https://github.com/igrigorik/em-synchrony/) Gem.
|
9
8
|
|
9
|
+
* For more information about `em-synchrony` usage check [Untangling Evented Code with Ruby Fibers](http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/).
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
Creates a MySQL connection pool. Parameters:
|
11
|
+
Check the [mysql2 documentation](https://github.com/brianmario/mysql2/blob/master/README.md) for the exact syntax and usage of the MySQL queries.
|
14
12
|
|
15
|
-
* `options`: A mandatory `Hash` with the following fields:
|
16
|
-
* `:name`: Mandatory field. Must be a `Symbol` with the name for this pool.
|
17
|
-
* `:pool_size`: The number of parallel MySQL connections to perform. By default 10.
|
18
|
-
* `:synchrony`: Whether to use [em-synchrony](https://github.com/igrigorik/em-synchrony/) or not. By default `false`.
|
19
13
|
|
20
|
-
|
14
|
+
## API
|
21
15
|
|
22
|
-
*NOTE:* There is no need to pass the option `:async => true` in `db_data`. That is automatically done by the library.
|
23
16
|
|
17
|
+
### Method `OverSIP::Modules::Mysql.add_pool(options)`
|
24
18
|
|
25
|
-
|
19
|
+
Creates a MySQL connection pool by receiving a mandatory `options` (a `Hash`) with the following fields:
|
20
|
+
* `:pool_name`: Mandatory field. Must be a `Symbol` with the name for this pool.
|
21
|
+
* `:pool_size`: The number of parallel MySQL connections to perform. By default 10.
|
22
|
+
* The rest of the fields will be passed to each [`Mysql2::EM::Client.new`](https://github.com/brianmario/mysql2#connection-options) being created.
|
26
23
|
|
27
|
-
|
24
|
+
The method allows passing a block which would be later called by passing as argument each generated `Mysql2::EM::Client` instance.
|
28
25
|
|
26
|
+
The created connection pool is an instance of [`EventMachine::Synchrony::ConnectionPool`](https://github.com/igrigorik/em-synchrony/blob/master/lib/em-synchrony/connection_pool.rb).
|
29
27
|
|
30
28
|
|
29
|
+
### Method `OverSIP::Modules::Mysql.pool(pool_name)`
|
31
30
|
|
32
|
-
|
31
|
+
Retrieves a previously created pool with the given name. Raises an `ArgumentError` if the given name does not exist in the list of created pools.
|
33
32
|
|
34
|
-
When creating a pool with `options[:synchrony] => false` (default behaviour) the obtained pool is a [`EventMachine::Pool`](https://github.com/ibc/EventMachine-LE/blob/master/lib/em/pool.rb) instance and thus, it requires the following usage:
|
35
33
|
|
36
34
|
|
37
|
-
|
35
|
+
## Usage Example
|
38
36
|
|
39
37
|
On top of `/etc/oversip/server.rb`:
|
40
38
|
|
41
39
|
```
|
42
40
|
require "oversip-mod-mysql"
|
41
|
+
```
|
42
|
+
|
43
|
+
|
44
|
+
Within the `OverSIP::SipEvents.on_initialize()` method in `/etc/oversip/server.rb`:
|
43
45
|
|
46
|
+
```
|
44
47
|
def (OverSIP::SystemEvents).on_initialize
|
45
|
-
OverSIP::M::Mysql.add_pool(
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
:username => "oversip",
|
54
|
-
:password => "xxxxxx",
|
55
|
-
:database => "oversip",
|
56
|
-
:cast_booleans => true,
|
57
|
-
:symbolize_keys => true
|
58
|
-
}
|
59
|
-
)
|
48
|
+
OverSIP::M::Mysql.add_pool({
|
49
|
+
:pool_name => :my_db,
|
50
|
+
:pool_size => 5,
|
51
|
+
:host => "localhost",
|
52
|
+
:username => "oversip",
|
53
|
+
:password => "xxxxxx",
|
54
|
+
:database => "oversip"
|
55
|
+
}) {|conn| log_info "MySQL created connection: #{conn.inspect}" }
|
60
56
|
end
|
61
57
|
```
|
62
58
|
|
63
59
|
Somewhere within the `OverSIP::SipEvents.on_request()` method in `/etc/oversip/server.rb`:
|
64
60
|
|
65
61
|
```
|
66
|
-
pool = OverSIP::M::Mysql.pool(:
|
62
|
+
pool = OverSIP::M::Mysql.pool(:my_db)
|
67
63
|
|
68
64
|
begin
|
69
|
-
pool.
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
request.reply 404, "User not found in DB"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
query.errback do |error|
|
85
|
-
log_error "DB async query error: #{error.inspect}"
|
86
|
-
request.reply 500, "DB async query error"
|
87
|
-
end
|
65
|
+
result = pool.query "SELECT * FROM users WHERE user = \'#{request.from.user}\'"
|
66
|
+
log_info "DB query result: #{result.to_a.inspect}"
|
67
|
+
if result.any?
|
68
|
+
# Add a X-Header with value the 'custom_header' field of the table row:
|
69
|
+
request.set_header "X-Header", result.first["custom_header"]
|
70
|
+
proxy = ::OverSIP::SIP::Proxy.new :proxy_out
|
71
|
+
proxy.route request
|
72
|
+
return
|
73
|
+
else
|
74
|
+
request.reply 404, "User not found in DB"
|
75
|
+
return
|
88
76
|
end
|
89
77
|
|
90
78
|
rescue ::Mysql2::Error => e
|
91
|
-
log_error "DB
|
79
|
+
log_error "DB query error:"
|
92
80
|
log_error e
|
93
|
-
request.reply 500, "DB
|
81
|
+
request.reply 500, "DB query error"
|
82
|
+
return
|
94
83
|
end
|
95
84
|
```
|
96
85
|
|
97
86
|
|
98
|
-
##
|
99
|
-
|
100
|
-
When creating a pool with `options[:synchrony] => true` the obtained pool is a [`EventMachine::Synchrony::ConnectionPool`](https://github.com/igrigorik/em-synchrony/blob/master/lib/em-synchrony/connection_pool.rb) instance.
|
101
|
-
|
102
|
-
Please ensure you properly understand how [em-synchrony](https://github.com/igrigorik/em-synchrony/) works. Specially take into account that just the code within the `EM.synchrony do [...] end` block is executed serially. Code placed after that block is executed immediately, this is, *before* the serial code is executed. So if you want to use serial style coding write all your logic code within a `EM.synchrony do [...] end` block.
|
103
|
-
|
104
|
-
* For more information about `em-synchrony` usage check [Untangling Evented Code with Ruby Fibers](http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/).
|
105
|
-
|
106
|
-
|
107
|
-
### Example
|
108
|
-
|
109
|
-
On top of `/etc/oversip/server.rb`:
|
110
|
-
|
111
|
-
```
|
112
|
-
require "oversip-mod-mysql"
|
113
|
-
|
114
|
-
def (OverSIP::SystemEvents).on_initialize
|
115
|
-
OverSIP::M::Mysql.add_pool(
|
116
|
-
{
|
117
|
-
:name => :my_sync_db,
|
118
|
-
:pool_size => 5,
|
119
|
-
:synchrony => true
|
120
|
-
},
|
121
|
-
{
|
122
|
-
:host => "localhost",
|
123
|
-
:username => "oversip",
|
124
|
-
:password => "xxxxxx",
|
125
|
-
:database => "oversip",
|
126
|
-
:cast_booleans => true,
|
127
|
-
:symbolize_keys => true
|
128
|
-
}
|
129
|
-
)
|
130
|
-
end
|
131
|
-
```
|
132
|
-
|
133
|
-
Somewhere within the `OverSIP::SipEvents.on_request()` method in `/etc/oversip/server.rb`:
|
134
|
-
|
135
|
-
```
|
136
|
-
EM.synchrony do
|
137
|
-
pool = OverSIP::M::Mysql.pool(:my_sync_db)
|
138
|
-
|
139
|
-
begin
|
140
|
-
result = pool.query "SELECT * FROM users WHERE user = \'#{request.from.user}\'"
|
141
|
-
log_info "DB sync query result: #{result.to_a.inspect}"
|
142
|
-
if result.any?
|
143
|
-
# Add a X-Header with value the 'custom_header' field of the table row:
|
144
|
-
request.set_header "X-Header", result.first["custom_header"]
|
145
|
-
proxy = ::OverSIP::SIP::Proxy.new :proxy_out
|
146
|
-
proxy.route request
|
147
|
-
else
|
148
|
-
request.reply 404, "User not found in DB"
|
149
|
-
end
|
150
|
-
|
151
|
-
rescue ::Mysql2::Error => e
|
152
|
-
log_error "DB sync query error:"
|
153
|
-
log_error e
|
154
|
-
request.reply 500, "DB sync query error"
|
155
|
-
end
|
156
|
-
end
|
157
|
-
```
|
87
|
+
## Limitations
|
158
88
|
|
89
|
+
[mysql2](https://github.com/brianmario/mysql2) driver has auto reconnection support (which is forced by `oversip-mod-mysql` by setting the field `options[:reconnect] => true`). Unfortunatelly the auto reconnect feature of `mysql2` driver is blocking which means that, in case the MySQL server goes down, OverSIP will get frozen during the auto reconnection attempt.
|
159
90
|
|
160
|
-
## Using sync and async styles together
|
161
91
|
|
162
|
-
|
92
|
+
## Dependencies
|
163
93
|
|
164
|
-
|
94
|
+
* Ruby > 1.9.2.
|
95
|
+
* [oversip](http://www.oversip.net) Gem >= 1.3.0.
|
96
|
+
* MySQL development library (the package `libmysqlclient-dev` in Debian/Ubuntu).
|
165
97
|
|
166
98
|
|
167
99
|
## Installation
|
@@ -173,4 +105,6 @@ When a sync pool is created, the library loads `em-synchrony/mysql2` which overr
|
|
173
105
|
|
174
106
|
## Author
|
175
107
|
|
176
|
-
Iñaki Baz Castillo
|
108
|
+
Iñaki Baz Castillo
|
109
|
+
* Mail: ibc@aliax.net
|
110
|
+
* Github profile: [@ibc](https://github.com/ibc)
|
data/lib/oversip-mod-mysql.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require "mysql2/em"
|
2
|
-
|
3
1
|
require "oversip-mod-mysql/version.rb"
|
4
|
-
|
2
|
+
|
3
|
+
require "em-synchrony"
|
4
|
+
require "em-synchrony/mysql2"
|
5
5
|
|
6
6
|
|
7
7
|
module OverSIP
|
@@ -12,58 +12,46 @@ module OverSIP
|
|
12
12
|
extend ::OverSIP::Logger
|
13
13
|
|
14
14
|
DEFAULT_POOL_SIZE = 10
|
15
|
-
DEFAULT_SYNCHRONY = false
|
16
15
|
|
17
16
|
@log_id = "Mysql module"
|
18
17
|
@pools = {}
|
19
18
|
|
20
|
-
def self.add_pool options
|
19
|
+
def self.add_pool options
|
21
20
|
raise ::ArgumentError, "`options' must be a Hash" unless options.is_a? ::Hash
|
22
|
-
raise ::ArgumentError, "`db_data' must be a Hash" unless db_data.is_a? ::Hash
|
23
21
|
|
24
|
-
|
25
|
-
pool_size
|
26
|
-
synchrony ||= DEFAULT_SYNCHRONY
|
22
|
+
pool_name = options.delete(:pool_name)
|
23
|
+
pool_size = options.delete(:pool_size) || DEFAULT_POOL_SIZE
|
27
24
|
|
28
|
-
raise ::ArgumentError, "`options[:
|
25
|
+
raise ::ArgumentError, "`options[:pool_name]' must be a Symbol" unless pool_name.is_a? ::Symbol
|
29
26
|
raise ::ArgumentError, "`options[:pool_size]' must be a positive Fixnum" unless pool_size.is_a? ::Fixnum and pool_size > 0
|
30
27
|
|
31
|
-
|
32
|
-
db_data[:reconnect] = true
|
28
|
+
block = ::Proc.new if block_given?
|
33
29
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
30
|
+
::OverSIP::SystemCallbacks.on_started do
|
31
|
+
log_info "Adding MySQL connection pool (name: #{pool_name.inspect}, size: #{pool_size})..."
|
32
|
+
@pools[pool_name] = ::EM::Synchrony::ConnectionPool.new(size: pool_size) do
|
33
|
+
# Avoid the hash to be modified internally.
|
34
|
+
new_options = options.clone
|
35
|
+
# Force DB autoreconnect.
|
36
|
+
new_options[:reconnect] = true
|
42
37
|
|
43
|
-
|
44
|
-
log_system_info "Adding a sync pool with name #{name.inspect}..."
|
45
|
-
@pools[name] = ::EM::Synchrony::ConnectionPool.new(size: pool_size) do
|
46
|
-
::Mysql2::EM::Client.new(db_data)
|
47
|
-
end
|
48
|
-
end
|
38
|
+
conn = ::Mysql2::EM::Client.new(new_options)
|
49
39
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
log_system_info "Adding an async pool with name #{name.inspect}..."
|
54
|
-
pool = @pools[name] = ::EM::Pool.new
|
55
|
-
pool_size.times do
|
56
|
-
pool.add ::Mysql2::EM::Client.new(db_data)
|
57
|
-
end
|
40
|
+
# Call the given block by passing conn as argument.
|
41
|
+
block.call(conn) if block
|
42
|
+
conn
|
58
43
|
end
|
59
44
|
end
|
60
45
|
end # def self.add_pool
|
61
46
|
|
62
|
-
def self.pool
|
63
|
-
pool = @pools[
|
64
|
-
raise ::ArgumentError, "no pool with `name' #{
|
47
|
+
def self.pool pool_name
|
48
|
+
pool = @pools[pool_name]
|
49
|
+
raise ::ArgumentError, "no pool with `name' #{pool_name.inspect}" unless pool
|
65
50
|
pool
|
66
51
|
end
|
52
|
+
class << self
|
53
|
+
alias :get_pool :pool
|
54
|
+
end
|
67
55
|
|
68
56
|
end # module Mysql
|
69
57
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oversip-mod-mysql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-10-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: oversip
|
16
|
-
requirement: &
|
16
|
+
requirement: &7556920 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.
|
21
|
+
version: 1.3.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *7556920
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: mysql2
|
27
|
-
requirement: &
|
27
|
+
requirement: &7556360 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,12 +32,9 @@ dependencies:
|
|
32
32
|
version: 0.3.11
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
36
|
-
description:
|
37
|
-
proxy.
|
38
|
-
(by using ''em-synchrony'' Gem).
|
39
|
-
|
40
|
-
'
|
35
|
+
version_requirements: *7556360
|
36
|
+
description: oversip-mod-mysql provides an easy to use MySQL connector for OverSIP
|
37
|
+
proxy.
|
41
38
|
email:
|
42
39
|
- ibc@aliax.net
|
43
40
|
executables: []
|
@@ -46,7 +43,6 @@ extra_rdoc_files: []
|
|
46
43
|
files:
|
47
44
|
- lib/oversip-mod-mysql.rb
|
48
45
|
- lib/oversip-mod-mysql/version.rb
|
49
|
-
- lib/oversip-mod-mysql/mysql2_em_client.rb
|
50
46
|
- README.md
|
51
47
|
- AUTHORS
|
52
48
|
- LICENSE
|