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 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