dynashard 0.2.0 → 0.3.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 +84 -5
- data/VERSION +1 -1
- data/dynashard.gemspec +4 -2
- data/spec/db/database.yml +16 -0
- metadata +6 -5
data/README.md
CHANGED
@@ -2,17 +2,22 @@
|
|
2
2
|
|
3
3
|
This package provides database sharding functionality for ActiveRecord models.
|
4
4
|
|
5
|
-
Sharding is disabled by default and is enabled with
|
6
|
-
sharding behavior to be enabled globally or only for specific environments
|
7
|
-
|
5
|
+
Sharding is disabled by default and is enabled with `Dynashard.enable`. This allows
|
6
|
+
sharding behavior to be enabled globally or only for specific environments; for example,
|
7
|
+
production environments could be sharded while development environments could
|
8
8
|
use a single database.
|
9
9
|
|
10
10
|
Models may be configured to determine the appropriate shard (database connection) to
|
11
|
-
use based on context defined prior to performing queries.
|
11
|
+
use based on context defined prior to performing queries. Different
|
12
|
+
models may shard using different contexts.
|
12
13
|
|
13
14
|
class Widget < ActiveRecord::Base
|
14
15
|
shard :by => :user
|
15
16
|
end
|
17
|
+
|
18
|
+
class Doohickie < ActiveRecord::Base
|
19
|
+
shard :by => :vhost
|
20
|
+
end
|
16
21
|
|
17
22
|
class WidgetController < ApplicationController
|
18
23
|
around_filter :set_shard_context
|
@@ -20,12 +25,15 @@ use based on context defined prior to performing queries.
|
|
20
25
|
def index
|
21
26
|
# Widgets will be loaded using the connection for the current user's shard
|
22
27
|
@widgets = Widget.find(:all)
|
28
|
+
|
29
|
+
# Doohickies will be loaded using the connection for the vhost's shard
|
30
|
+
@doohickies = Doohickie.find(:all)
|
23
31
|
end
|
24
32
|
|
25
33
|
private
|
26
34
|
|
27
35
|
def set_shard_context
|
28
|
-
Dynashard.with_context(:user => current_user.shard) do
|
36
|
+
Dynashard.with_context(:user => current_user.shard, :vhost => request.env['HTTP_HOST']) do
|
29
37
|
yield
|
30
38
|
end
|
31
39
|
end
|
@@ -65,6 +73,77 @@ association's owner.
|
|
65
73
|
|
66
74
|
New associations are saved on the Company's shard.
|
67
75
|
|
76
|
+
Shard context values may be a valid argument to establish_connection()
|
77
|
+
such as a string reference to a configuration from config/database.yml
|
78
|
+
or a hash with database connection parameters. Values may also be an
|
79
|
+
object that responds to :call and returns a valid argument to
|
80
|
+
establish_connection().
|
81
|
+
|
82
|
+
Load widgets from a shard defined in database.yml
|
83
|
+
|
84
|
+
$ cat config/database.yml
|
85
|
+
|
86
|
+
development:
|
87
|
+
database: db/development.sqlite3
|
88
|
+
<<: *defaults
|
89
|
+
|
90
|
+
shard1:
|
91
|
+
database: db/shard1.sqlite3
|
92
|
+
<<: *defaults
|
93
|
+
|
94
|
+
shard2:
|
95
|
+
database: db/shard2.sqlite3
|
96
|
+
<<: *defaults
|
97
|
+
|
98
|
+
> @widgets = Dynashard.with_context(:user => 'shard1') { Widget.find(:all) }
|
99
|
+
=> [#<Widget id:1>, #<Widget id:2>]
|
100
|
+
|
101
|
+
Load widgets from a shard using a hash of connection params
|
102
|
+
|
103
|
+
> conn = {:adapter => 'sqlite3', :database => 'db/shard3.sqlite3'}
|
104
|
+
> @widgets = Dynashard.with_context(:user => conn) { Widget.find(:all) }
|
105
|
+
=> [#<Widget id:1>, #<Widget id:2>]
|
106
|
+
|
107
|
+
Create a widget using a method to determine the shard
|
108
|
+
|
109
|
+
widget_shard = lambda do
|
110
|
+
# Store widgets by month/day
|
111
|
+
{:adapter => 'sqlite3', :database => "db/dayslice#{Time.now.strftime("%m%d")}"}
|
112
|
+
end
|
113
|
+
|
114
|
+
> Time.now
|
115
|
+
=> Mon Jan 31 17:37:23 -0800 2011
|
116
|
+
|
117
|
+
> widget_shard.call
|
118
|
+
=> {:database=>"db/dayslice0131", :adapter=>"sqlite3"}
|
119
|
+
|
120
|
+
> new_widget = Dynashard.with_context(:user => widget_shard) do
|
121
|
+
Widget.create(:name => 'The newest of the widgets')
|
122
|
+
end
|
123
|
+
=> <#Widget id:3>
|
124
|
+
|
125
|
+
Use a Rails initializer for one-time configuration of shard context
|
126
|
+
|
127
|
+
$ cat config/initializers/dynashard.rb
|
128
|
+
|
129
|
+
# Put user-sharded data on the smallest shard
|
130
|
+
Dynashard.shard_context[:user] = lambda do
|
131
|
+
Shard.order(:size).find(:first).dsn
|
132
|
+
end
|
133
|
+
|
134
|
+
> new_widget = Widget.create(:name => 'Put this on the smallest shard')
|
135
|
+
=> <#Widget id:4>
|
136
|
+
|
137
|
+
Use with_context to override an earlier context setting
|
138
|
+
|
139
|
+
> Dynashard.shard_context[:user] = 'shard1'
|
140
|
+
> new_widget = Widget.create(:name => 'Put this on shard1')
|
141
|
+
=> <#Widget id:5>
|
142
|
+
> new_widget = Dynashard.with_context(:user => 'shard2') do
|
143
|
+
Widget.create(:name => 'Put this on shard2')
|
144
|
+
do
|
145
|
+
> <#Widget id:6>
|
146
|
+
|
68
147
|
## TODO: add gotcha section, eg:
|
69
148
|
|
70
149
|
- uniqueness validations should be scoped by whatever is sharding
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/dynashard.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{dynashard}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Nick Hengeveld"]
|
12
|
-
s.date = %q{2011-01
|
12
|
+
s.date = %q{2011-02-01}
|
13
13
|
s.description = %q{Dynashard allows you to shard your ActiveRecord models. Models can be configured to shard based on context that can be defined dynamically.}
|
14
14
|
s.email = %q{nickh@verticalresponse.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -32,6 +32,8 @@ Gem::Specification.new do |s|
|
|
32
32
|
"lib/dynashard/validations.rb",
|
33
33
|
"spec/associations_spec.rb",
|
34
34
|
"spec/connection_handler_spec.rb",
|
35
|
+
"spec/db/database.yml",
|
36
|
+
"spec/db/schema.rb",
|
35
37
|
"spec/dynashard_spec.rb",
|
36
38
|
"spec/model_spec.rb",
|
37
39
|
"spec/spec_helper.rb",
|
@@ -0,0 +1,16 @@
|
|
1
|
+
shared: &shared
|
2
|
+
adapter: sqlite3
|
3
|
+
pool: 5
|
4
|
+
timeout: 5000
|
5
|
+
|
6
|
+
test:
|
7
|
+
database: <%= plugin_test_dir %>/db/base.sqlite3
|
8
|
+
<<: *shared
|
9
|
+
|
10
|
+
shard1:
|
11
|
+
database: <%= plugin_test_dir %>/db/shard1.sqlite3
|
12
|
+
<<: *shared
|
13
|
+
|
14
|
+
shard2:
|
15
|
+
database: <%= plugin_test_dir %>/db/shard2.sqlite3
|
16
|
+
<<: *shared
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 3
|
8
8
|
- 0
|
9
|
-
version: 0.
|
9
|
+
version: 0.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Nick Hengeveld
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-01
|
17
|
+
date: 2011-02-01 00:00:00 -08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -140,13 +140,14 @@ files:
|
|
140
140
|
- lib/dynashard/validations.rb
|
141
141
|
- spec/associations_spec.rb
|
142
142
|
- spec/connection_handler_spec.rb
|
143
|
+
- spec/db/database.yml
|
144
|
+
- spec/db/schema.rb
|
143
145
|
- spec/dynashard_spec.rb
|
144
146
|
- spec/model_spec.rb
|
145
147
|
- spec/spec_helper.rb
|
146
148
|
- spec/support/factories.rb
|
147
149
|
- spec/support/models.rb
|
148
150
|
- spec/validation_spec.rb
|
149
|
-
- spec/db/schema.rb
|
150
151
|
has_rdoc: true
|
151
152
|
homepage: http://github.com/nickh/dynashard
|
152
153
|
licenses:
|
@@ -161,7 +162,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
161
162
|
requirements:
|
162
163
|
- - ">="
|
163
164
|
- !ruby/object:Gem::Version
|
164
|
-
hash:
|
165
|
+
hash: 2742474365578406990
|
165
166
|
segments:
|
166
167
|
- 0
|
167
168
|
version: "0"
|