activerecord-sqlserver-adapter-mirroring 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ /pkg/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in activerecord-sqlserver-adapter-mirroring.gemspec
4
+ gemspec
@@ -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
@@ -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,2 @@
1
+ require "activerecord-sqlserver-adapter"
2
+ require "activerecord-sqlserver-adapter-mirroring/mirroring"
@@ -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
@@ -0,0 +1,8 @@
1
+ test:
2
+ adapter: sqlserver
3
+ host: primary
4
+ database: activerecord_unittest_mirroring
5
+ username: rails
6
+ password:
7
+ mirror:
8
+ host: mirror
@@ -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
@@ -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