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.
@@ -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