oversip-mod-mysql 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,167 +1,99 @@
1
1
  # oversip-mod-mysql
2
2
 
3
- `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. The library allows both pure async style (via callbacks) or serial style (by using [em-synchrony](https://github.com/igrigorik/em-synchrony/) Gem).
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
- ## API
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
- ### Method `OverSIP:M:Mysql.add_pool(options, db_data)`
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
- * `db_data`: A mandatory `Hash` that will be passed to [`Mysql2::EM::Client.new`](https://github.com/brianmario/mysql2#connection-options).
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
- ### Method `OverSIP:M:Mysql.pool(name)`
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
- 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.
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
- ## Pure async style usage
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
- ### Example
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
- :name => :my_async_db,
48
- :pool_size => 5,
49
- :synchrony => false
50
- },
51
- {
52
- :host => "localhost",
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(:my_async_db)
62
+ pool = OverSIP::M::Mysql.pool(:my_db)
67
63
 
68
64
  begin
69
- pool.perform do |db_conn|
70
- query = db_conn.aquery "SELECT * FROM users WHERE user = \'#{request.from.user}\'"
71
-
72
- query.callback do |result|
73
- log_info "DB async query result: #{result.to_a.inspect}"
74
- if result.any?
75
- # Add a X-Header with value the 'custom_header' field of the table row:
76
- request.set_header "X-Header", result.first["custom_header"]
77
- proxy = ::OverSIP::SIP::Proxy.new
78
- proxy.route request
79
- else
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 async query error:"
79
+ log_error "DB query error:"
92
80
  log_error e
93
- request.reply 500, "DB async query error"
81
+ request.reply 500, "DB query error"
82
+ return
94
83
  end
95
84
  ```
96
85
 
97
86
 
98
- ## Sync style usage with `em-synchrony`
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
- A pool created with `OverSIP:M:Mysql.add_pool()` method must be sync or async. However the user can set two pools, the first one sync and the second one sync.
92
+ ## Dependencies
163
93
 
164
- When a sync pool is created, the library loads `em-synchrony/mysql2` which overrides the `Mysql2::EM::Client#query()` method. So if *at least* one of your pools uses sync style then you must use the `Mysql2::EM::Client#aquery()` method for the async pool (which is an alias of the original `query()` method).
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 <ibc@aliax.net> (Github [@ibc](https://github.com/ibc)).
108
+ Iñaki Baz Castillo
109
+ * Mail: ibc@aliax.net
110
+ * Github profile: [@ibc](https://github.com/ibc)
@@ -1,7 +1,7 @@
1
- require "mysql2/em"
2
-
3
1
  require "oversip-mod-mysql/version.rb"
4
- require "oversip-mod-mysql/mysql2_em_client.rb"
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, db_data
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
- name, pool_size, synchrony = options.values_at(:name, :pool_size, :synchrony)
25
- pool_size ||= DEFAULT_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[:name]' must be a Symbol" unless name.is_a? ::Symbol
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
- # Forcing DB autoreconnect.
32
- db_data[:reconnect] = true
28
+ block = ::Proc.new if block_given?
33
29
 
34
- # Use em-synchrony for serial coding.
35
- if synchrony
36
- begin
37
- require "em-synchrony"
38
- require "em-synchrony/mysql2"
39
- rescue ::LoadError
40
- OverSIP::Launcher.fatal "em-synchrony not installed: gem install em-synchrony"
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
- OverSIP::SystemCallbacks.on_started do
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
- # Don't use em-synchrony but pure callbacks.
51
- else
52
- OverSIP::SystemCallbacks.on_started do
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 name
63
- pool = @pools[name]
64
- raise ::ArgumentError, "no pool with `name' #{name.inspect}" unless pool
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
 
@@ -4,8 +4,8 @@ module OverSIP
4
4
  module Mysql
5
5
  module Version
6
6
  MAJOR = 0
7
- MINOR = 0
8
- TINY = 1
7
+ MINOR = 1
8
+ TINY = 0
9
9
  DEVEL = nil # Set to nil for stable releases.
10
10
  end
11
11
 
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.1
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-09-04 00:00:00.000000000 Z
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: &16825480 !ruby/object:Gem::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.2.0
21
+ version: 1.3.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *16825480
24
+ version_requirements: *7556920
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: mysql2
27
- requirement: &17963820 !ruby/object:Gem::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: *17963820
36
- description: ! 'oversip-mod-mysql provides an easy to use MySQL connector for OverSIP
37
- proxy. The library allows both pure async style (via callbacks) or serial style
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
@@ -1,8 +0,0 @@
1
- module Mysql2
2
- module EM
3
- class Client
4
- # Allow the aquery() method even if 'em-synchrony' is not loaded.
5
- alias :aquery :query
6
- end
7
- end
8
- end