methodmissing-mysqlplus_adapter 1.0.2 → 1.0.3

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.textile CHANGED
@@ -14,6 +14,8 @@ Grab mysqlplus ....
14
14
 
15
15
  ... then update config/database.yml
16
16
 
17
+ <pre>
18
+ <code>
17
19
  production:
18
20
  adapter: mysqlplus
19
21
  database: myapp_production
@@ -21,6 +23,8 @@ Grab mysqlplus ....
21
23
  password:
22
24
  host: localhost
23
25
  pool: 10
26
+ </code>
27
+ </pre>
24
28
 
25
29
  h2. Why Bother ?
26
30
 
@@ -30,7 +34,11 @@ The ever popular "mysql ruby":http://www.tmtm.org/en/mysql/ruby/ do *not* schedu
30
34
 
31
35
  Rails since release 2.2 support connection pooling and Thread safety ( at the framework level mind you, plugins, gems and user code aside ) through :
32
36
 
37
+ <pre>
38
+ <code>
33
39
  config.threadsafe!
40
+ </code>
41
+ </pre>
34
42
 
35
43
  This configuration hook removes the global Dispatcher lock and yields one connection from the pool per request / response cycle.
36
44
 
@@ -40,6 +48,8 @@ h2. Configuration Options
40
48
 
41
49
  An additional connection specification element, *warmup* is available that attempts to establish the pooled connections in advance.This may be useful for high traffic environments where it makes sense to setup connections when bouncing the App and not let initial incoming requests be hogged with Mysql connection overheads.
42
50
 
51
+ <pre>
52
+ <code>
43
53
  production:
44
54
  adapter: mysqlplus
45
55
  database: myapp_production
@@ -48,22 +58,34 @@ An additional connection specification element, *warmup* is available that attem
48
58
  host: localhost
49
59
  pool: 10
50
60
  warmup: true
61
+ </code>
62
+ </pre>
51
63
 
52
64
  h3. Deferrable Results
53
65
 
54
66
  Deferred results simulate lazy loading in a background Thread, through another Mysql connection, other than the one the current Thread has acquired.This type of workflow assumes a decent Connection Pool size of 5 to 10 connections.
55
67
 
68
+ <pre>
69
+ <code>
56
70
  # Immediate yield control back to the current Thread as the query is pushed to the background.
57
71
  # Yields an instance of ActiveRecord::Deferrable::Result
58
72
  #
59
73
  Post.find( :first, :defer => true )
74
+ </code>
75
+ </pre>
60
76
 
61
77
  A deferred result blocks when any method's invoked on the result set right away.
62
78
 
79
+ <pre>
80
+ <code>
63
81
  Post.find( :first, :defer => true ).title
82
+ </code>
83
+ </pre>
64
84
 
65
85
  This concept is quite useful in an MVC context, allowing the controller to fetch results, defer fetching them to the background and reference them in the view, allowing an undefined period / time slice during which rendering, template setup etc. may occur.
66
86
 
87
+ <pre>
88
+ <code>
67
89
  class PostsController
68
90
 
69
91
  def index
@@ -73,17 +95,37 @@ This concept is quite useful in an MVC context, allowing the controller to fetch
73
95
  end
74
96
 
75
97
  end
98
+ </code>
99
+ </pre>
76
100
 
77
101
  Since ActiveRecord 2.1 preloading favors multiple efficient queries to cumbersome and mostly slow JOINs.Those secondary queries can easily be pushed down different connections.
78
102
 
103
+ <pre>
104
+ <code>
79
105
  # Use 3 connections from the pool : 1 x Post, 1 x Comment and 1 x Vote
80
106
  #
81
107
  Post.find(:all, :limit => 10, :include => [:comments, :votes], :defer => true )
108
+ </code>
109
+ </pre>
82
110
 
83
111
  h2. Garbage Collection
84
112
 
85
113
  There's some experimental GC patches "available":http://github.com/oldmoe/mysqlplus/tree/with_async_validation - the mysql ruby gem forces GC every 20 queries, that's a guaranteed GC cycle every 5th request for a request with a 4 query overhead.This adapter will automatically detect the presence of those patches and disable the forced GC runs.
86
114
 
115
+ <pre>
116
+ <code>
117
+ methodmissing:mysqlplus lourens$ ruby test/gc_benchmark.rb
118
+ Rehearsal ----------------------------------------------
119
+ With GC 0.440000 0.020000 0.460000 ( 0.741424)
120
+ Without GC 0.040000 0.030000 0.070000 ( 0.327787)
121
+ ------------------------------------- total: 0.530000sec
122
+
123
+ user system total real
124
+ With GC 0.430000 0.030000 0.460000 ( 0.725934)
125
+ Without GC 0.040000 0.010000 0.050000 ( 0.311233)
126
+ </code>
127
+ </pre>
128
+
87
129
  h2. Stability
88
130
 
89
131
  In (pre)-production use at a handful of sites and the test suite is designed to run against the existing ActiveRecord suite.
@@ -92,6 +134,4 @@ h2. TODO
92
134
 
93
135
  * Experiment with turning off query_with_result for certain queries.
94
136
 
95
- * Deferred inserts / updates - *dangerous* INSERT DELAYED for Innodb
96
-
97
- * 1.9 compatibility testing
137
+ * Deferred inserts / updates - *dangerous* INSERT DELAYED for Innodb
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 2
2
+ :patch: 3
3
3
  :major: 1
4
4
  :minor: 0
@@ -7,6 +7,7 @@ module ActiveRecord
7
7
  def install!
8
8
  ActiveRecord::Base.send :extend, SingletonMethods
9
9
  ar_eigenclass::VALID_FIND_OPTIONS << :defer
10
+ ActiveRecord::Calculations::CALCULATIONS_OPTIONS << :defer
10
11
  alias_deferred :find, :find_by_sql, :preload_associations, :find_every
11
12
  end
12
13
 
@@ -19,7 +19,7 @@ module ActiveRecord
19
19
  begin
20
20
  deferrable.call
21
21
  rescue => exception
22
- exception
22
+ exception
23
23
  ensure
24
24
  ::ActiveRecord::Base.connection_pool.release_connection
25
25
  end
@@ -0,0 +1,20 @@
1
+ require "#{File.dirname(__FILE__)}/helper"
2
+
3
+ Mysqlplus::Test.prepare!
4
+
5
+ class ConnectionPoolTest < ActiveSupport::TestCase
6
+
7
+ def teardown
8
+ ActiveRecord::Base.clear_all_connections!
9
+ ActiveRecord::Base.establish_connection( Mysqlplus::Test::CONNECTION_SPEC )
10
+ super
11
+ end
12
+
13
+ test "should not establish connections in a lazy manner when warmed up" do
14
+ ActiveRecord::Base.connection_pool.expects(:checkout_new_connection).never
15
+ 5.times do
16
+ ActiveRecord::Base.connection_pool.checkout
17
+ end
18
+ end
19
+
20
+ end
@@ -10,18 +10,18 @@ class MacroTest < ActiveSupport::TestCase
10
10
  super
11
11
  end
12
12
 
13
- def test_should_be_able_to_find_records_in_a_background_thread
13
+ test "should be able to find records in a background thread" do
14
14
  ActiveRecord::Base.connection_pool.expects(:release_connection).twice
15
15
  assert_equal MysqlUser.find(:first, :defer => true), MysqlUser.find(:first)
16
16
  assert_instance_of MysqlUser, MysqlUser.find(:first, :defer => true)
17
17
  end
18
18
 
19
- def test_should_be_able_to_find_records_by_sql_background_thread
19
+ test "should be able to find records by sql background thread" do
20
20
  ActiveRecord::Base.connection_pool.expects(:release_connection).once
21
21
  assert_equal MysqlUser.find_by_sql("SELECT * FROM mysql.user WHERE User = 'root'", true), MysqlUser.find(:all, :conditions => ['user.User = ?', 'root'])
22
22
  end
23
23
 
24
- def test_should_be_able_to_preload_related_records_on_multiple_connections
24
+ test "should be able to preload related records on multiple connections" do
25
25
  ActiveRecord::Base.connection_pool.expects(:release_connection).twice
26
26
  assert_instance_of MysqlUser, MysqlUser.find( :first, :defer => true, :include => :mysql_user_info)
27
27
  sleep(0.5)
@@ -29,4 +29,4 @@ class MacroTest < ActiveSupport::TestCase
29
29
 
30
30
  end
31
31
 
32
- Thread.list.each{|t| t.join unless t == Thread.main }
32
+ Thread.list.each{|t| t.join unless t == Thread.main }
@@ -0,0 +1,35 @@
1
+ require "#{File.dirname(__FILE__)}/../helper"
2
+
3
+ Mysqlplus::Test.prepare!
4
+
5
+ class ResultTest < ActiveSupport::TestCase
6
+
7
+ def teardown
8
+ ActiveRecord::Base.clear_all_connections!
9
+ ActiveRecord::Base.establish_connection( Mysqlplus::Test::CONNECTION_SPEC )
10
+ super
11
+ end
12
+
13
+ test "should be able to raise exceptions from the background Thread" do
14
+ assert_raises( StandardError ) do
15
+ ActiveRecord::Deferrable::Result.new do
16
+ raise StandardError
17
+ end.to_s
18
+ end
19
+ end
20
+
21
+ test "should release the checked out connection for the background Thread at all times" do
22
+ ActiveRecord::Base.connection_pool.expects(:release_connection).once
23
+ ActiveRecord::Deferrable::Result.new do
24
+ raise StandardError
25
+ end
26
+ end
27
+
28
+ test "should only block when an immediate result is required" do
29
+ ActiveRecord::Deferrable::Result.any_instance.expects(:validate!).never
30
+ ActiveRecord::Deferrable::Result.new do
31
+ sleep(5)
32
+ end
33
+ end
34
+
35
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: methodmissing-mysqlplus_adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Lourens Naud\xC3\xA9"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-09 00:00:00 -08:00
12
+ date: 2009-02-12 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -32,11 +32,13 @@ files:
32
32
  - lib/active_record/connection_adapters/mysqlplus_adapter/deferrable/macro.rb
33
33
  - lib/active_record/connection_adapters/mysqlplus_adapter/deferrable/result.rb
34
34
  - lib/active_record/connection_adapters/mysqlplus_adapter.rb
35
+ - test/connection_pool_test.rb
35
36
  - test/connections
36
37
  - test/connections/mysqlplus
37
38
  - test/connections/mysqlplus/connection.rb
38
39
  - test/deferrable
39
40
  - test/deferrable/macro_test.rb
41
+ - test/deferrable/result_test.rb
40
42
  - test/helper.rb
41
43
  - test/models
42
44
  - test/models/mysql_user.rb