activerecord-sqlserver-adapter-mirroring 0.1.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/.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
|