mysql_replication_status 0.1.1 → 0.1.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.
Files changed (2) hide show
  1. data/lib/mysql_replication_status.rb +165 -0
  2. metadata +2 -1
@@ -0,0 +1,165 @@
1
+ # utility to check the replication status between MySQL master and slave
2
+ # dbs set up to replicate to each other
3
+ #
4
+ # All that is needed is to specify the two dbs by their rails database
5
+ # config (environment) names (e.g. 'staging_master', 'staging_slave' or
6
+ # whatever).
7
+ #
8
+ # examples:
9
+ #
10
+ # # specify both master and slave db configs
11
+ # status = MysqlReplicationStatus.new(:master => 'master', :slave => 'slave)
12
+ # # default slave to the current environment
13
+ # status = MysqlReplicationStatus.new(:master => 'master')
14
+ # # override the default time to cache the statuses (in seconds)
15
+ # status = MysqlReplicationStatus.new(:master => 'master', :slave => 'slave,
16
+ # :refresh_time => 10)
17
+ # # override the default database config file (not recommended)
18
+ # status = MysqlReplicationStatus.new(:master => 'master', :slave => 'slave,
19
+ # :db_config_file => 'foofile.txt')
20
+ #
21
+ # TODO: did a quick google search on the class name and didn't have anything
22
+ # returned, but do we have any sort of namespace we want to use?....
23
+ #-------------------------------------------------------------------------------
24
+ class MysqlReplicationStatus
25
+
26
+ # exception raised if the class detects that either master or slave do not
27
+ # appear to be configured for replication
28
+ #-----------------------------------------------------------------------------
29
+ class NoReplicationError < Exception; end
30
+
31
+
32
+ # constructor accepts environment labels for the dbs to query replication
33
+ # status for. if one or the other is not specified, will use the
34
+ # rails environment that the class is currently running under. this
35
+ # object can cache status to reduce traffic on master and slave if this
36
+ # class's objects are to be called frequently (see :refresh_time option)
37
+ # options:
38
+ # :master => string containing environment to query the master db status
39
+ # :slave => string containing environment to query the slave db status
40
+ # (one or the other is optional, but never both)
41
+ # :refresh_time => how many seconds can elapse since last time the dbs
42
+ # were polled before we need to hit dbs again (in between
43
+ # any status methods called will just return cached
44
+ # values). optional, default => 1 (cache very briefly).
45
+ # recommend not setting this to 0, as calls like
46
+ # slave_running? will result in two db hits.
47
+ # :db_config_file => file containing database config settings. optional,
48
+ # default is rails default (recommended)
49
+ #-----------------------------------------------------------------------------
50
+ def initialize(options)
51
+ if options.blank? || (!options.include?(:master) &&
52
+ !options.include?(:slave))
53
+ raise "Invalid options configuration: should be a hash that includes " +
54
+ "either :master or :slave or both"
55
+ end
56
+
57
+ # if asked to override database config file, use the special init()
58
+ # function
59
+ if options[:db_config_file]
60
+ MultipleConnectionHandler.init(:config_file => options[:db_config_file])
61
+ end
62
+
63
+ @master_env = options[:master] || RAILS_ENV
64
+ @slave_env = options[:slave] || RAILS_ENV
65
+
66
+ @slave_status = nil
67
+ @master_status = nil
68
+
69
+ @refresh_time = options[:refresh_time] || 1
70
+ @last_refresh = nil
71
+ end
72
+
73
+
74
+ # force a refresh of the cached status. overrides :refresh_time option.
75
+ #-----------------------------------------------------------------------------
76
+ def refresh
77
+ @master_status = MultipleConnectionHandler.connection(@master_env).
78
+ execute("SHOW MASTER STATUS").all_hashes[0]
79
+ @slave_status = MultipleConnectionHandler.connection(@slave_env).
80
+ execute("SHOW SLAVE STATUS").all_hashes[0]
81
+
82
+ @last_refresh = Time.now
83
+
84
+ if @master_status.blank? && @slave_status.blank?
85
+ raise NoReplicationError,
86
+ "Neither master (#{@master_env}) nor slave (#{@slave_env}) " +
87
+ "appear to be configured for replication"
88
+ elsif @master_status.blank?
89
+ raise NoReplicationError,
90
+ "Master (#{@master_env}) does not appear to be configured for replication"
91
+ elsif @slave_status.blank?
92
+ raise NoReplicationError,
93
+ "Slave (#{@slave_env}) does not appear to be configured for replication"
94
+ end
95
+ end
96
+
97
+
98
+ # indicates if both IO and SQL threads are running
99
+ #-----------------------------------------------------------------------------
100
+ def slave_running?
101
+ cache_check_or_refresh
102
+
103
+ slave_io_running? && slave_sql_running?
104
+ end
105
+
106
+
107
+ # indicates if master and slave currently have same log file and log file
108
+ # position. note that if returns false, doesn't necessarily mean anything is
109
+ # wrong...just that slave is lagging. but if returns true, it may be that
110
+ # slave_running? is false.
111
+ #-----------------------------------------------------------------------------
112
+ def master_and_slave_in_sync?
113
+ cache_check_or_refresh
114
+
115
+ @master_status['Position'] == @slave_status['Exec_Master_Log_Pos'] &&
116
+ @master_status['File'] == @slave_status['Relay_Master_Log_File']
117
+ end
118
+
119
+
120
+ # returns true if the slave IO thread is running
121
+ #-----------------------------------------------------------------------------
122
+ def slave_io_running?
123
+ cache_check_or_refresh
124
+
125
+ @slave_status['Slave_IO_Running'].downcase == 'yes'
126
+ end
127
+
128
+
129
+ # returns true if the slave SQL thread is running
130
+ #-----------------------------------------------------------------------------
131
+ def slave_sql_running?
132
+ cache_check_or_refresh
133
+
134
+ @slave_status['Slave_SQL_Running'].downcase == 'yes'
135
+ end
136
+
137
+
138
+ # return a hashed version of the result of running SHOW SLAVE STATUS
139
+ #-----------------------------------------------------------------------------
140
+ def raw_slave_status
141
+ cache_check_or_refresh
142
+
143
+ @slave_status
144
+ end
145
+
146
+
147
+ # return a hashed version of the result of running SHOW MASTER STATUS
148
+ #-----------------------------------------------------------------------------
149
+ def raw_master_status
150
+ cache_check_or_refresh
151
+
152
+ @master_status
153
+ end
154
+
155
+ private
156
+
157
+ # check to see if the cache needs refreshing and do so if so.
158
+ #-----------------------------------------------------------------------------
159
+ def cache_check_or_refresh
160
+ if @last_refresh.nil? || @last_refresh + @refresh_time < Time.now
161
+ refresh
162
+ end
163
+ end
164
+
165
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mysql_replication_status
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - bmpercy
@@ -31,6 +31,7 @@ extensions: []
31
31
  extra_rdoc_files: []
32
32
 
33
33
  files:
34
+ - lib/mysql_replication_status.rb
34
35
  - README
35
36
  has_rdoc: true
36
37
  homepage: