nightcrawler 0.0.1 → 0.0.2

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/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ *.db
@@ -0,0 +1,20 @@
1
+ ## each instance controls the complete set of similar shards
2
+ #class Mosaic
3
+
4
+ ## a parent namespace for all our sharded models
5
+ #module ShardPool; end
6
+
7
+ ## name should be unique across mosaics
8
+ #def initialize(name, keys_configs, &block=nil)
9
+ #@name = name
10
+ #@keys_configs = keys_configs
11
+ #@block = block
12
+ #@shards = {}
13
+ #@keys_configs.each do |k,v|
14
+ #@shard_klass[k] =
15
+ #end
16
+
17
+
18
+ #end
19
+
20
+
@@ -1,3 +1,3 @@
1
1
  module Nightcrawler
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,101 @@
1
+ #require 'spec_helper'
2
+
3
+ #describe Mosaic do
4
+ #before(:each) do
5
+ #@builder = ShardBuilder.new(3)
6
+ #shard_configs = (1..3).inject({}) {|h,i| h.merge "shard#{i}".to_sym => @builder.config(i)}
7
+ #Mosaic.new(shard_configs) do
8
+ #class Parent < Shard; end
9
+ #class Child < Shard; end
10
+ #end
11
+ #end
12
+
13
+ #it "should provide the correct model for the given shard" do
14
+ #(1..3).each do |i|
15
+ #Parent.shard("shard#{i}".to_sym).first.name.split(']')[0].should== "[shard ##{i}"
16
+ #end
17
+ #end
18
+
19
+ #it "should provide the correct model for the given shard" do
20
+ #Mosaic.shards.each do |shard|
21
+ #shard::Parent.first.name.split(']')[0].should== "[shard ##{shard.key}"
22
+ #end
23
+ #end
24
+ #end
25
+
26
+ #class Comment < ActiveRecord::Base
27
+ #include Nightcrawler::Sharding
28
+ #establish_connection :adapter => "sqlite3", :database => File.expand_path(File.join(File.dirname(__FILE__), "db", "master.db"))
29
+
30
+ #validates_presence_of :shard_key
31
+
32
+ #shard_by :shard_key
33
+
34
+ #def self.find_shard(value)
35
+ #"shard#{value}".to_sym
36
+ #end
37
+
38
+ #def self.shard_for(key)
39
+ #$shards[key]
40
+ #end
41
+
42
+ #end
43
+
44
+
45
+ #@shard_builder = TestShardBuilder.new(4)
46
+
47
+ #before(:each) do
48
+ #@shard_builder.build
49
+ #end
50
+
51
+ #after(:each) do
52
+ #@shard_builder.destroy
53
+ #end
54
+
55
+
56
+
57
+ #it "should do something" do
58
+ #Comment.shard(:shard1).should == CommentShard1
59
+ #end
60
+ #it "should create second shard" do
61
+ #Comment.shard(:shard2).should == CommentShard2
62
+ #end
63
+
64
+ #describe "creating a comment" do
65
+ #before(:all) do
66
+ #@comment = Comment.shard(:shard1).create!(:shard_key => 1, :comment => "comment number 1")
67
+ #end
68
+ #after(:all) do
69
+ #@comment.destroy
70
+ #end
71
+ #it "should exist on the first shard" do
72
+ #Comment.shard(:shard1).where(:comment => "comment number 1").first.should == @comment
73
+ #end
74
+ #it "should not exist on the second shard" do
75
+ #Comment.shard(:shard2).where(:comment => "comment number 1").should be_empty
76
+ #end
77
+ #end
78
+
79
+ #describe "search for a comment" do
80
+ #before(:all) do
81
+ #@comment1 = Comment.shard(:shard1).create!(:shard_key => 1, :comment => "blah")
82
+ #@comment2 = Comment.shard(:shard2).create!(:shard_key => 2, :comment => "blah")
83
+ #end
84
+ #after(:all) do
85
+ #@comment1.destroy rescue nil
86
+ #@comment2.destroy rescue nil
87
+ #end
88
+ #it "should lookup shard based on relation" do
89
+ #Comment.where(:shard_key => 1).where(:comment => "blah").size.should == 1
90
+ #Comment.where(:shard_key => 1).where(:comment => "blah").first.should be_a CommentShard1
91
+ #Comment.where(:shard_key => 2).size.should == 1
92
+ #Comment.where(:shard_key => 2).first.should be_a Comment
93
+ #Comment.where(:shard_key => 2).first.should be_a CommentShard2
94
+ #end
95
+
96
+ #it "should not do blind relation" do
97
+ #lambda { Comment.where(:comment => "blah").to_a }.should raise_exception
98
+ #end
99
+ #end
100
+ #end
101
+
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+ require 'active_record'
3
+
4
+ # ActiveRecord classes do not like to be inside anonymous modules-- if you want to anonymize, then you'll need a nested module!
5
+
6
+
7
+ describe ShardBuilder do
8
+ context "testing the shard builder" do
9
+
10
+ it "should raze the db dir as expected" do
11
+ builder = ShardBuilder.new
12
+ builder.raze
13
+ Dir.entries(File.expand_path("../db", __FILE__)).length.should == 2
14
+ FileUtils.touch File.expand_path("../db/blahblah", __FILE__)
15
+ FileUtils.touch File.expand_path("../db/yo.db", __FILE__)
16
+ Dir.entries(File.expand_path("../db", __FILE__)).length.should == 4
17
+ builder.raze
18
+ Dir.entries(File.expand_path("../db", __FILE__)).length.should == 2
19
+ end
20
+
21
+ it "should be able to connect to a single shard no problem" do
22
+ builder = ShardBuilder.new(1,3)
23
+ ActiveRecord::Base.establish_connection(builder.config(1))
24
+ module A
25
+ class Parent < ActiveRecord::Base; end
26
+ end
27
+ A::Parent.all.length.should == 3
28
+ A::Parent.all.each do |p|
29
+ p.name.should match(/^\[shard #1\]/)
30
+ end
31
+ end
32
+
33
+ # unfortunately this seems to require setting the table name!
34
+ it "should be able to leverage sandwich classes to hold the connections and still have relationships on a single shard" do
35
+ builder = ShardBuilder.new(1,3,5)
36
+ module B
37
+ class Shard < ActiveRecord::Base; end
38
+ class Parent < Shard; set_table_name "parents"; has_many :children end
39
+ class Child < Shard; set_table_name "children"; end
40
+ end
41
+ B::Shard.establish_connection(builder.config(1))
42
+ B::Parent.all.length.should == 3
43
+ B::Parent.all.each do |p|
44
+ p.name.should match(/^\[shard #1\]/)
45
+ p.children.length.should == 5
46
+ p.children.each do |c|
47
+ c.name.should match(/^\[shard #1\]/)
48
+ end
49
+ end
50
+ end
51
+
52
+ # unfortunately this seems to require setting the table name!
53
+ it "should be able to have relationships in each shard" do
54
+ builder = ShardBuilder.new(2,3,5)
55
+ module C1
56
+ class Shard < ActiveRecord::Base; end
57
+ class Parent < Shard; set_table_name "parents"; has_many :children end
58
+ class Child < Shard; set_table_name "children"; end
59
+ end
60
+ module C2
61
+ class Shard < ActiveRecord::Base; end
62
+ class Parent < Shard; set_table_name "parents"; has_many :children end
63
+ class Child < Shard; set_table_name "children"; end
64
+ end
65
+ C1::Shard.establish_connection(builder.config(1))
66
+ C2::Shard.establish_connection(builder.config(2))
67
+ C1::Parent.all.length.should == 3
68
+ C1::Parent.all.each do |p|
69
+ p.name.should match(/^\[shard #1\]/)
70
+ p.children.length.should == 5
71
+ p.children.each do |c|
72
+ c.name.should match(/^\[shard #1\]/)
73
+ end
74
+ end
75
+ C2::Parent.all.length.should == 3
76
+ C2::Parent.all.each do |p|
77
+ p.name.should match(/^\[shard #2\]/)
78
+ p.children.length.should == 5
79
+ p.children.each do |c|
80
+ c.name.should match(/^\[shard #2\]/)
81
+ end
82
+ end
83
+ end
84
+
85
+ end
86
+ end
87
+
88
+
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'active_record'
3
+
4
+ # a utility class used only for tests that builds out a number of shards with parent & child tables prepopulated with some test data
5
+ class ShardBuilder
6
+ class Child < ActiveRecord::Base; end;
7
+ class Parent < ActiveRecord::Base; end;
8
+
9
+ def initialize(shard_count=3, parent_count=3, child_count=5)
10
+ @shard_count = shard_count
11
+ @parent_count = parent_count
12
+ @child_count = child_count
13
+ raze
14
+ build
15
+ end
16
+
17
+ def build
18
+ (1..@shard_count).each do |i|
19
+ base = ActiveRecord::Base
20
+ base.establish_connection(config(i))
21
+ base.connection.create_table "children" do |t|
22
+ t.integer :parent_id
23
+ t.string :name
24
+ end
25
+ base.connection.create_table "parents" do |t|
26
+ t.integer :id
27
+ t.string :name
28
+ end
29
+ (1..@parent_count).each do |j|
30
+ (1..@child_count).each do |k|
31
+ Child.create :parent_id=>j, :name=>"[shard ##{i}] child(##{k}) for parent(##{j})"
32
+ end
33
+ Parent.create :name=>"[shard ##{i}] parent(#{j})"
34
+ end
35
+ base.remove_connection(base)
36
+ end
37
+ end
38
+
39
+ def raze
40
+ FileUtils.rm_rf File.expand_path("../../db", __FILE__)
41
+ FileUtils.mkdir_p File.expand_path("../../db", __FILE__)
42
+ end
43
+
44
+ def config(shard_index)
45
+ {:adapter => "sqlite3", :database => File.expand_path("../../db/shard#{shard_index}.db", __FILE__)}
46
+ end
47
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: nightcrawler
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Joshua Lane, Michael Prior
@@ -10,7 +10,8 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-02 00:00:00 Z
13
+ date: 2011-05-04 00:00:00 -04:00
14
+ default_executable:
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
16
17
  name: rspec
@@ -108,13 +109,18 @@ files:
108
109
  - lib/nightcrawler.rb
109
110
  - lib/nightcrawler/manager.rb
110
111
  - lib/nightcrawler/migration.rb
112
+ - lib/nightcrawler/mosaic.rb
111
113
  - lib/nightcrawler/relation.rb
112
114
  - lib/nightcrawler/shard.rb
113
115
  - lib/nightcrawler/shard_descriptor.rb
114
116
  - lib/nightcrawler/version.rb
115
117
  - nightcrawler.gemspec
116
118
  - spec/manager_spec.rb
119
+ - spec/mosaic_spec.rb
120
+ - spec/shard_builder_spec.rb
117
121
  - spec/spec_helper.rb
122
+ - spec/support/shard_builder.rb
123
+ has_rdoc: true
118
124
  homepage: ""
119
125
  licenses: []
120
126
 
@@ -138,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
144
  requirements: []
139
145
 
140
146
  rubyforge_project: nightcrawler
141
- rubygems_version: 1.7.2
147
+ rubygems_version: 1.6.2
142
148
  signing_key:
143
149
  specification_version: 3
144
150
  summary: Minimal sharding solution for AR