acts_as_partitionable 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2007 Revolution Health Group LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,102 @@
1
+ == Introduction
2
+
3
+ ActsAsPartitionable provides support for using multiple databases to support
4
+ data partitioning schemes for existing models.
5
+ This plugin allows models marked as acts_as_partitionable to specify database
6
+ partitions to and explicit names to reference those partitions using existing
7
+ models. As part of this plugin connection pooling is provided so that many
8
+ different models may share the same database for partitions without forcing each
9
+ partition model object to inherit from a common base class.
10
+
11
+ == Disclaimer
12
+
13
+ As part of our strategy to address data partitioning as stated in our blog
14
+ entry:
15
+ http://revolutiononrails.blogspot.com/2007/04/ActsAsReadonlyable-to-support-
16
+ read-only.html
17
+
18
+ We wrote this plugin in preparation to using slave DBs but we are not going to
19
+ have those until May 2007.
20
+ So even though the code is covered with tests (see
21
+ svn://rubyforge.org/var/svn/actsaspartition/trunk/test/unit/partitionable_test.r
22
+ b), it has not yet been used in a production environment.
23
+
24
+ We will have a discovery period in May when the code is likely to be improved so
25
+ for now you can use is at your own risk.
26
+ Meanwhile, we would be happy to fix any issue revealed. Drop us a line at rails-
27
+ trunk [ at ] revolution DOT com.
28
+
29
+ Using this plugin should not be your first step in application
30
+ optimization/scaling or even the second one.
31
+ Before installing it make sure you understand the implication of leveraging
32
+ multiple DBs (for example, the potential for cross DB joins).
33
+
34
+ == Example
35
+
36
+ === Sample Model
37
+
38
+ class SomeModel < ActiveRecord::Base
39
+ # use the read_only database from the database.yml
40
+ acts_as_partitionable :name => "partition_1", :access => :readonly,
41
+ :db_config => :read_only
42
+
43
+ # use the default database for partition_2
44
+ acts_as_partitionable :name => "partition_2"
45
+
46
+ # use the a specific w/r database for partition_3
47
+ acts_as_partitionable :name => "partition_3", :db_config =>
48
+ :some_model_partition
49
+
50
+ # Specify the database configuration from a hash
51
+ acts_as_partitionable :access => :readonly, :db_config => {:adapter =>
52
+ "mysql", :database => "partionable_db_test", :username => "root", :password =>
53
+ "", :host => "localhost"}
54
+ end
55
+
56
+ === Sample DB Config
57
+
58
+ dbs:
59
+
60
+ database: master_db
61
+ host: master-host
62
+
63
+ read_only:
64
+ database: slave_db
65
+ host: slave-host
66
+
67
+
68
+ some_model_partition:
69
+ database: slave_db_2
70
+ host: slave-host
71
+
72
+ === Usage
73
+
74
+ r = SomeModel.readonly.find(:first) # executes against the read_only db -
75
+ slave_db
76
+ r.field = 'value'
77
+ r.save! # raises ActiveRecord::ReadOnlyRecord
78
+ r.readonly? # true
79
+
80
+ t = SomeModel.partition_3.find(:first) # executes against slave_db_2
81
+ t.field = 'some value'
82
+ t.save! # success to partition_3
83
+
84
+
85
+ == Installation
86
+
87
+ As plugin:
88
+ script/plugin install
89
+ svn://rubyforge.org/var/svn/actsaspartition/trunk/vendor/plugins/acts_as_partiti
90
+ onable
91
+
92
+
93
+ == License
94
+
95
+ ActsAsPartitionable is released under the MIT license.
96
+
97
+
98
+ == Support
99
+
100
+ The plugin RubyForge page is http://rubyforge.org/projects/actsaspartition
101
+
102
+
@@ -0,0 +1,94 @@
1
+ # CONFIDENTIAL AND PROPRIETARY. © 2007 Revolution Health Group LLC. All rights reserved.
2
+ # This source code may not be disclosed to others, used or reproduced without the written permission of Revolution Health Group.
3
+ module Acts
4
+ module Partitionable
5
+
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+ end
9
+
10
+ module ClassMethods
11
+ def acts_as_partitionable?
12
+ true
13
+ end
14
+
15
+ # Readonly Simple Sample:
16
+ # class User
17
+ # acts_as_partitionable :access => :readonly, :db_config => ...
18
+ # end
19
+ # User.readonly do
20
+ # me = find(1) # DB hit
21
+ # end
22
+ # - or -
23
+ # User.readonly.find(:all)
24
+ #
25
+ #
26
+ # :access => [:readonly, :readwrite (default), :writeonly]
27
+ #
28
+ def acts_as_partitionable(options = {})
29
+ # default options
30
+ default_partition_name = "partition"
31
+ options = {:access => :readwrite, :name => default_partition_name}.merge(options)
32
+
33
+ partition_name = options[:name]
34
+
35
+ partition_db_klass_readonly = false
36
+ if options[:access] == :readonly
37
+ partition_db_klass_readonly = true
38
+ include ReadonlyInstanceMethods if partition_name == default_partition_name
39
+ end
40
+
41
+ if options[:db_config].is_a?(Hash)
42
+ db_config = options[:db_config]
43
+ elsif options[:db_config].is_a?(Symbol) or options[:db_config].is_a?(String)
44
+ begin
45
+ db_config = configurations[RAILS_ENV].merge(configurations[RAILS_ENV][options[:db_config].to_s])
46
+ rescue
47
+ raise ::ActiveRecord::ConfigurationError.new
48
+ end
49
+ end
50
+
51
+ partition_db_klass ||= eval <<-TOS
52
+ class #{self.name}Partitionable#{partition_name} < #{self.name}
53
+ # setting abstract_class to true so that ActiveRecord doesn't look
54
+ # for a db table for this base model class
55
+ self.abstract_class = true
56
+ def self.find_every(options)
57
+ (options ||= {})[:readonly] = true if #{partition_db_klass_readonly}
58
+ super(options)
59
+ end
60
+ def self.readonly?; #{partition_db_klass_readonly}; end
61
+ end
62
+ #{self.name}Partitionable#{partition_name}
63
+ TOS
64
+ partition_db_klass.establish_connection(db_config)
65
+
66
+ class_eval <<-PART_PROC_END
67
+ def self.#{partition_name}(&block)
68
+ return #{partition_db_klass}.module_eval(&block) if block_given?
69
+ #{partition_db_klass}
70
+ end
71
+ PART_PROC_END
72
+ end # acts_as_partitionable
73
+
74
+
75
+ module ReadonlyInstanceMethods #:nodoc:
76
+ def self.included(base) # :nodoc:
77
+ base.extend ClassMethods
78
+ end
79
+
80
+ module ClassMethods
81
+
82
+ def readonly(&block)
83
+ self.partition(&block)
84
+ end
85
+
86
+ end # ClassMethods
87
+ end # ReadonlyInstanceMethods
88
+
89
+ end # ClassMethods
90
+
91
+ end # Partitionable
92
+ end # Acts
93
+
94
+ ActiveRecord::Base.send :include, Acts::Partitionable
@@ -0,0 +1,64 @@
1
+ # CONFIDENTIAL AND PROPRIETARY. © 2007 Revolution Health Group LLC. All rights reserved.
2
+ # This source code may not be disclosed to others, used or reproduced without the written permission of Revolution Health Group.
3
+ module ActiveRecord
4
+ class Base
5
+ class << self
6
+ alias_method :no_cp_remove_connection, :remove_connection
7
+ alias_method :no_cp_establish_connection, :establish_connection
8
+
9
+ @@pooled_connections ||= {}
10
+ def pooled_connections
11
+ @@pooled_connections[Thread.current.object_id] ||= {}
12
+ end
13
+
14
+ def close_all_connections
15
+ pooled_connections.each do | key, value |
16
+ pooled_connections.delete(key)
17
+ active_connections.select { |klass, konn| no_cp_remove_connection(klass.constantize) if konn == value[:connection] }
18
+ end
19
+ end
20
+
21
+ def remove_connection(klass=self)
22
+ konn = active_connections[klass.name]
23
+ conn_key = nil
24
+ pooled_connections.each { |key, value| conn_key = key if value != nil && value[:connection] == konn }
25
+ if conn_key != nil
26
+ pooled_connections[conn_key][:count] -= 1
27
+ if pooled_connections[conn_key][:count] > 0
28
+ # remove it from the active list so that AR wont disconnect until 0 references
29
+ active_connections.delete(klass.name)
30
+ else
31
+ # must be time to clean up.
32
+ pooled_connections.delete(conn_key)
33
+ end
34
+ end
35
+ no_cp_remove_connection(klass)
36
+ end # remove_connection
37
+
38
+ def establish_connection(spec = nil)
39
+ if spec != nil and spec.kind_of?(ActiveRecord::Base::ConnectionSpecification)
40
+ @partitionable_adapter_methods ||= []
41
+ if not @partitionable_adapter_methods.include?(spec.adapter_method.to_s)
42
+ @partitionable_adapter_methods << (spec.adapter_method.to_s)
43
+ self.class_eval <<-REUSE_END
44
+ def self.#{spec.adapter_method}(config)
45
+ conn_key = config.to_s
46
+ if not pooled_connections.key?(conn_key)
47
+ pooled_connections[conn_key] = { :connection => super(config), :count => 1 }
48
+ elsif pooled_connections[conn_key] != nil
49
+ pooled_connections[conn_key][:count] += 1
50
+ end
51
+ pooled_connections[conn_key][:connection] rescue nil
52
+ end
53
+ REUSE_END
54
+ end
55
+ end
56
+ no_cp_establish_connection(spec)
57
+ end # establish_connection
58
+ end
59
+ end # Pool
60
+ end # Connection
61
+
62
+ #ActiveRecord::Base.send :include, Connection::Pool
63
+ #ActiveRecord::Base.extend Connection::Pool::ConnectionReuseMethods
64
+
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.0
3
+ specification_version: 1
4
+ name: acts_as_partitionable
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2007-04-17 00:00:00 -04:00
8
+ summary: acts_as_partitionable allows one to use multiple DBs to partition data for models
9
+ require_paths:
10
+ - lib
11
+ email: rails-trunk@revolution.com
12
+ homepage:
13
+ rubyforge_project:
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - RHG Team
31
+ files:
32
+ - lib/acts_as_partitionable.rb
33
+ - lib/connection_pool.rb
34
+ - README
35
+ - MIT-LICENSE
36
+ test_files: []
37
+
38
+ rdoc_options: []
39
+
40
+ extra_rdoc_files:
41
+ - README
42
+ - MIT-LICENSE
43
+ executables: []
44
+
45
+ extensions: []
46
+
47
+ requirements: []
48
+
49
+ dependencies: []
50
+