activerecord-sqlserver-adapter-mirroring 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +33 -0
- data/README +0 -0
- data/Rakefile +13 -0
- data/VERSION +1 -0
- data/activerecord-sqlserver-adapter-mirroring.gemspec +24 -0
- data/lib/activerecord-sqlserver-adapter-mirroring.rb +2 -0
- data/lib/activerecord-sqlserver-adapter-mirroring/mirroring.rb +87 -0
- data/test/database.yml +8 -0
- data/test/test_change_connection_params.rb +73 -0
- data/test/test_helper.rb +61 -0
- data/test/test_mirroring.rb +40 -0
- metadata +73 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
/pkg/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
activerecord-sqlserver-adapter-mirroring (0.0.1)
|
5
|
+
activerecord-sqlserver-adapter (~> 3.2.3)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activemodel (3.2.3)
|
11
|
+
activesupport (= 3.2.3)
|
12
|
+
builder (~> 3.0.0)
|
13
|
+
activerecord (3.2.3)
|
14
|
+
activemodel (= 3.2.3)
|
15
|
+
activesupport (= 3.2.3)
|
16
|
+
arel (~> 3.0.2)
|
17
|
+
tzinfo (~> 0.3.29)
|
18
|
+
activerecord-sqlserver-adapter (3.2.3)
|
19
|
+
activerecord (~> 3.2.0)
|
20
|
+
activesupport (3.2.3)
|
21
|
+
i18n (~> 0.6)
|
22
|
+
multi_json (~> 1.0)
|
23
|
+
arel (3.0.2)
|
24
|
+
builder (3.0.0)
|
25
|
+
i18n (0.6.0)
|
26
|
+
multi_json (1.3.4)
|
27
|
+
tzinfo (0.3.33)
|
28
|
+
|
29
|
+
PLATFORMS
|
30
|
+
ruby
|
31
|
+
|
32
|
+
DEPENDENCIES
|
33
|
+
activerecord-sqlserver-adapter-mirroring!
|
data/README
ADDED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
4
|
+
desc 'Default: run unit tests.'
|
5
|
+
task :default => :test
|
6
|
+
|
7
|
+
desc 'Run tests.'
|
8
|
+
Rake::TestTask.new(:test) do |t|
|
9
|
+
t.libs << 'lib'
|
10
|
+
t.libs << 'test'
|
11
|
+
t.pattern = 'test/**/test_*.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "activerecord-sqlserver-adapter-mirroring"
|
6
|
+
s.version = File.read('VERSION').strip
|
7
|
+
s.authors = ["Igor Anicaca"]
|
8
|
+
s.email = ["ianic@minus5.hr"]
|
9
|
+
s.homepage = "https://github.com/minus5/activerecord-sqlserver-adapter-mirroring"
|
10
|
+
s.summary = "Database mirroring support for Rails activerecord-sqlserver-adapter"
|
11
|
+
s.description = "Database mirroring support for Rails activerecord-sqlserver-adapter"
|
12
|
+
|
13
|
+
s.rubyforge_project = "activerecord-sqlserver-adapter-mirroring"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
# specify any dependencies here; for example:
|
21
|
+
# s.add_development_dependency "rspec"
|
22
|
+
# s.add_runtime_dependency "rest-client"
|
23
|
+
s.add_dependency "activerecord-sqlserver-adapter", "~> 3.2.3"
|
24
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
def self.db_mirroring_status
|
4
|
+
|
5
|
+
#Returns hash with db mirroring status details
|
6
|
+
# if mirroring is inactive for current database returns empty hash
|
7
|
+
connection.select_one("
|
8
|
+
SELECT
|
9
|
+
DB_NAME(database_id) database_name
|
10
|
+
, mirroring_role_desc
|
11
|
+
, mirroring_safety_level_desc
|
12
|
+
, mirroring_state_desc
|
13
|
+
, mirroring_safety_sequence
|
14
|
+
, mirroring_role_sequence
|
15
|
+
, mirroring_partner_instance
|
16
|
+
, mirroring_witness_name
|
17
|
+
, mirroring_witness_state_desc
|
18
|
+
, mirroring_failover_lsn
|
19
|
+
FROM sys.database_mirroring
|
20
|
+
WHERE mirroring_guid IS NOT NULL
|
21
|
+
and database_id = db_id();
|
22
|
+
") || {}
|
23
|
+
end
|
24
|
+
|
25
|
+
#Returns true if current database is db mirroring principal
|
26
|
+
def self.db_mirroring_active?
|
27
|
+
db_mirroring_status["mirroring_role_desc"] == "PRINCIPAL"
|
28
|
+
end
|
29
|
+
|
30
|
+
#Returns true if db mirroring is in synchronized state
|
31
|
+
def self.db_mirroring_synchronized?
|
32
|
+
db_mirroring_status["mirroring_state_desc"] == "SYNCHRONIZED"
|
33
|
+
end
|
34
|
+
|
35
|
+
#Returns current database server name
|
36
|
+
def self.server_name
|
37
|
+
connection.select_value("select @@servername")
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module ActiveRecord
|
44
|
+
module ConnectionAdapters
|
45
|
+
|
46
|
+
module SqlServerMirroring
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def mirror_defined?
|
51
|
+
!@connection_options[:mirror].nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
def switch_to_mirror
|
55
|
+
mirror_root = @connection_options[:mirror] || @connection_options['mirror']
|
56
|
+
mirror_root.each_key do |key|
|
57
|
+
tmp = mirror_root[key]
|
58
|
+
mirror_root[key] = @connection_options[key.to_sym] || @connection_options[key]
|
59
|
+
@connection_options[key.to_sym] = tmp
|
60
|
+
@connection_options[key] = tmp
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
class SQLServerAdapter
|
67
|
+
include ActiveRecord::ConnectionAdapters::SqlServerMirroring
|
68
|
+
|
69
|
+
def connect_with_mirroring
|
70
|
+
return connect_without_mirroring unless mirror_defined?
|
71
|
+
connect_without_mirroring rescue connect_to_mirror
|
72
|
+
connect_to_mirror if @auto_connecting && !active?
|
73
|
+
@connection
|
74
|
+
end
|
75
|
+
|
76
|
+
alias_method_chain :connect, :mirroring
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def connect_to_mirror
|
81
|
+
switch_to_mirror
|
82
|
+
connect_without_mirroring
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/test/database.yml
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestChangeConnectionParams < ActiveRecord::TestCase
|
4
|
+
|
5
|
+
def test_config
|
6
|
+
@model = DummyModel.new({
|
7
|
+
:adapter => :sqlserver,
|
8
|
+
:mode => :dblib,
|
9
|
+
:username => "sa",
|
10
|
+
:password => "cheese",
|
11
|
+
:database => "db_name",
|
12
|
+
:host => "primary_server",
|
13
|
+
:mirror => {
|
14
|
+
:host => "mirror_server",
|
15
|
+
:port => 1434,
|
16
|
+
:password => "mouse"
|
17
|
+
}
|
18
|
+
})
|
19
|
+
|
20
|
+
@model.send(:switch_to_mirror)
|
21
|
+
assert_mirror
|
22
|
+
@model.send(:switch_to_mirror)
|
23
|
+
assert_primary
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_config_with_string_keys
|
27
|
+
@model = DummyModel.new({
|
28
|
+
'adapter' => :sqlserver,
|
29
|
+
'mode' => :dblib,
|
30
|
+
'username'=> "sa",
|
31
|
+
'password'=> "cheese",
|
32
|
+
'database'=> "db_name",
|
33
|
+
'host' => "primary_server",
|
34
|
+
'mirror' => {
|
35
|
+
'host' => "mirror_server",
|
36
|
+
'port' => 1434,
|
37
|
+
'password'=> "mouse"
|
38
|
+
}
|
39
|
+
})
|
40
|
+
|
41
|
+
@model.send(:switch_to_mirror)
|
42
|
+
assert_mirror
|
43
|
+
@model.send(:switch_to_mirror)
|
44
|
+
assert_primary
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def assert_primary
|
50
|
+
assert_equal "primary_server" , value_for(:host)
|
51
|
+
assert_nil value_for(:port)
|
52
|
+
assert_equal "cheese" , value_for(:password)
|
53
|
+
assert_common
|
54
|
+
end
|
55
|
+
|
56
|
+
def assert_mirror
|
57
|
+
assert_equal "mirror_server" , value_for(:host)
|
58
|
+
assert_equal 1434 , value_for(:port)
|
59
|
+
assert_equal "mouse" , value_for(:password)
|
60
|
+
assert_common
|
61
|
+
end
|
62
|
+
|
63
|
+
def assert_common
|
64
|
+
assert_equal :sqlserver , value_for(:adapter)
|
65
|
+
assert_equal :dblib , value_for(:mode)
|
66
|
+
assert_equal "sa" , value_for(:username)
|
67
|
+
assert_equal "db_name" , value_for(:database)
|
68
|
+
end
|
69
|
+
|
70
|
+
def value_for(key)
|
71
|
+
@model.connection_options[key] || @model.connection_options[key.to_s]
|
72
|
+
end
|
73
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_record'
|
5
|
+
require 'active_model'
|
6
|
+
require 'pp'
|
7
|
+
|
8
|
+
$:.unshift "#{File.dirname(__FILE__)}/../"
|
9
|
+
$:.unshift "#{File.dirname(__FILE__)}/../lib/"
|
10
|
+
|
11
|
+
require 'activerecord-sqlserver-adapter-mirroring.rb'
|
12
|
+
|
13
|
+
config = YAML.load(File.read(File.join(File.dirname(__FILE__), "database.yml")))['test']
|
14
|
+
#ActiveRecord::Base.establish_connection(config)
|
15
|
+
|
16
|
+
#define model
|
17
|
+
class Programmer < ActiveRecord::Base
|
18
|
+
end
|
19
|
+
|
20
|
+
Programmer.establish_connection(config)
|
21
|
+
|
22
|
+
def setup_db
|
23
|
+
ActiveRecord::Schema.define do
|
24
|
+
|
25
|
+
Programmer.connection.create_table :programmers, :force => true do |t|
|
26
|
+
t.column :first_name, :string
|
27
|
+
t.column :last_name, :string
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def db_failover
|
34
|
+
Programmer.connection.execute("use master; ALTER DATABASE activerecord_unittest_mirroring SET PARTNER FAILOVER")
|
35
|
+
end
|
36
|
+
|
37
|
+
def failover
|
38
|
+
begin
|
39
|
+
db_failover
|
40
|
+
rescue
|
41
|
+
sleep 1
|
42
|
+
retry
|
43
|
+
end
|
44
|
+
Programmer.connection.reconnect!
|
45
|
+
print_current_server_name
|
46
|
+
end
|
47
|
+
|
48
|
+
def print_current_server_name
|
49
|
+
print "connected to #{Programmer.server_name}\n"
|
50
|
+
end
|
51
|
+
|
52
|
+
#dummy class to include SqlServerMirroring module, and test it
|
53
|
+
class DummyModel
|
54
|
+
include ActiveRecord::ConnectionAdapters::SqlServerMirroring
|
55
|
+
|
56
|
+
def initialize(options)
|
57
|
+
@connection_options = options
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_reader :connection_options
|
61
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestMirroring < ActiveRecord::TestCase
|
4
|
+
# self.use_transactional_fixtures = false
|
5
|
+
|
6
|
+
def setup
|
7
|
+
setup_db
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_working_with_two_servers
|
11
|
+
print_current_server_name
|
12
|
+
|
13
|
+
Programmer.create(:first_name => "Sasa", :last_name => "Juric")
|
14
|
+
assert_equal 1, Programmer.count
|
15
|
+
|
16
|
+
failover
|
17
|
+
|
18
|
+
Programmer.create(:first_name => "Goran", :last_name => "Pizent")
|
19
|
+
assert_equal 2, Programmer.count
|
20
|
+
|
21
|
+
failover
|
22
|
+
|
23
|
+
Programmer.create(:first_name => "Vedran", :last_name => "Skrnjug")
|
24
|
+
assert_equal 3, Programmer.count
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_status_flags
|
28
|
+
assert Programmer.db_mirroring_active?
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_mirroring_status
|
32
|
+
status = Programmer.db_mirroring_status
|
33
|
+
pp status
|
34
|
+
assert !status.empty?
|
35
|
+
assert_equal "activerecord_unittest_mirroring", status["database_name"]
|
36
|
+
assert_equal "PRINCIPAL", status["mirroring_role_desc"]
|
37
|
+
assert ["SYNCHRONIZED", "SYNCHRONIZING"].include? status["mirroring_state_desc"]
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activerecord-sqlserver-adapter-mirroring
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Igor Anicaca
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-30 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord-sqlserver-adapter
|
16
|
+
requirement: &70316027548400 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.2.3
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70316027548400
|
25
|
+
description: Database mirroring support for Rails activerecord-sqlserver-adapter
|
26
|
+
email:
|
27
|
+
- ianic@minus5.hr
|
28
|
+
executables: []
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- .gitignore
|
33
|
+
- Gemfile
|
34
|
+
- Gemfile.lock
|
35
|
+
- README
|
36
|
+
- Rakefile
|
37
|
+
- VERSION
|
38
|
+
- activerecord-sqlserver-adapter-mirroring.gemspec
|
39
|
+
- lib/activerecord-sqlserver-adapter-mirroring.rb
|
40
|
+
- lib/activerecord-sqlserver-adapter-mirroring/mirroring.rb
|
41
|
+
- test/database.yml
|
42
|
+
- test/test_change_connection_params.rb
|
43
|
+
- test/test_helper.rb
|
44
|
+
- test/test_mirroring.rb
|
45
|
+
homepage: https://github.com/minus5/activerecord-sqlserver-adapter-mirroring
|
46
|
+
licenses: []
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
requirements: []
|
64
|
+
rubyforge_project: activerecord-sqlserver-adapter-mirroring
|
65
|
+
rubygems_version: 1.8.11
|
66
|
+
signing_key:
|
67
|
+
specification_version: 3
|
68
|
+
summary: Database mirroring support for Rails activerecord-sqlserver-adapter
|
69
|
+
test_files:
|
70
|
+
- test/database.yml
|
71
|
+
- test/test_change_connection_params.rb
|
72
|
+
- test/test_helper.rb
|
73
|
+
- test/test_mirroring.rb
|