Skip to content

Commit 84d9d3d

Browse files
Merge pull request #34 from readysettech/new_status
Make the scheduler aware of the new readyset status
2 parents 672dc99 + 38a8ce3 commit 84d9d3d

File tree

2 files changed

+116
-47
lines changed

2 files changed

+116
-47
lines changed

src/hosts.rs

Lines changed: 91 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::time::Duration;
66
#[allow(dead_code)]
77
/// Defines the possible status of a host
88
#[derive(PartialEq, Clone, Copy)]
9-
pub enum HostStatus {
9+
pub enum ProxyStatus {
1010
/// backend server is fully operational
1111
Online,
1212
/// backend sever is temporarily taken out of use because of either too many connection errors in a time that was too short, or the replication lag exceeded the allowed threshold
@@ -17,25 +17,66 @@ pub enum HostStatus {
1717
OfflineHard,
1818
}
1919

20-
impl fmt::Display for HostStatus {
20+
impl fmt::Display for ProxyStatus {
2121
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2222
match self {
23-
HostStatus::Online => write!(f, "ONLINE"),
24-
HostStatus::Shunned => write!(f, "SHUNNED"),
25-
HostStatus::OfflineSoft => write!(f, "OFFLINE_SOFT"),
26-
HostStatus::OfflineHard => write!(f, "OFFLINE_HARD"),
23+
ProxyStatus::Online => write!(f, "ONLINE"),
24+
ProxyStatus::Shunned => write!(f, "SHUNNED"),
25+
ProxyStatus::OfflineSoft => write!(f, "OFFLINE_SOFT"),
26+
ProxyStatus::OfflineHard => write!(f, "OFFLINE_HARD"),
2727
}
2828
}
2929
}
3030

31-
impl From<String> for HostStatus {
31+
impl From<String> for ProxyStatus {
3232
fn from(s: String) -> Self {
3333
match s.to_uppercase().as_str() {
34-
"ONLINE" => HostStatus::Online,
35-
"SHUNNED" => HostStatus::Shunned,
36-
"OFFLINE_SOFT" => HostStatus::OfflineSoft,
37-
"OFFLINE_HARD" => HostStatus::OfflineHard,
38-
_ => HostStatus::Online,
34+
"ONLINE" => ProxyStatus::Online,
35+
"SHUNNED" => ProxyStatus::Shunned,
36+
"OFFLINE_SOFT" => ProxyStatus::OfflineSoft,
37+
"OFFLINE_HARD" => ProxyStatus::OfflineHard,
38+
_ => ProxyStatus::Online,
39+
}
40+
}
41+
}
42+
43+
impl From<ReadysetStatus> for ProxyStatus {
44+
fn from(status: ReadysetStatus) -> Self {
45+
match status {
46+
ReadysetStatus::Online => ProxyStatus::Online,
47+
ReadysetStatus::SnapshotInProgress => ProxyStatus::Shunned,
48+
ReadysetStatus::Maintenance => ProxyStatus::OfflineSoft,
49+
ReadysetStatus::Unknown => ProxyStatus::Shunned,
50+
}
51+
}
52+
}
53+
54+
#[derive(PartialEq, Clone, Copy)]
55+
pub enum ReadysetStatus {
56+
Online,
57+
SnapshotInProgress,
58+
Maintenance,
59+
Unknown,
60+
}
61+
62+
impl fmt::Display for ReadysetStatus {
63+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64+
match self {
65+
ReadysetStatus::Online => write!(f, "Online"),
66+
ReadysetStatus::SnapshotInProgress => write!(f, "Snapshot in progress"),
67+
ReadysetStatus::Maintenance => write!(f, "Maintenance mode"),
68+
ReadysetStatus::Unknown => write!(f, "Unknown"),
69+
}
70+
}
71+
}
72+
73+
impl From<String> for ReadysetStatus {
74+
fn from(s: String) -> Self {
75+
match s.to_lowercase().as_str() {
76+
"online" => ReadysetStatus::Online,
77+
"snapshot in progress" => ReadysetStatus::SnapshotInProgress,
78+
"maintenance mode" => ReadysetStatus::Maintenance,
79+
_ => ReadysetStatus::Unknown,
3980
}
4081
}
4182
}
@@ -44,7 +85,8 @@ impl From<String> for HostStatus {
4485
pub struct Host {
4586
hostname: String,
4687
port: u16,
47-
status: HostStatus,
88+
proxysql_status: ProxyStatus,
89+
readyset_status: ReadysetStatus,
4890
conn: Option<Conn>,
4991
}
5092

@@ -62,7 +104,7 @@ impl Host {
62104
/// # Returns
63105
///
64106
/// A new `Host` instance.
65-
pub fn new(hostname: String, port: u16, status: String, config: &Config) -> Host {
107+
pub fn new(hostname: String, port: u16, proxysql_status: String, config: &Config) -> Host {
66108
let conn = match Conn::new(
67109
OptsBuilder::new()
68110
.ip_or_hostname(Some(hostname.clone()))
@@ -80,7 +122,8 @@ impl Host {
80122
return Host {
81123
hostname,
82124
port,
83-
status: HostStatus::from(status),
125+
proxysql_status: ProxyStatus::from(proxysql_status),
126+
readyset_status: ReadysetStatus::Unknown,
84127
conn: None,
85128
};
86129
}
@@ -89,7 +132,8 @@ impl Host {
89132
Host {
90133
hostname,
91134
port,
92-
status: HostStatus::from(status),
135+
proxysql_status: ProxyStatus::from(proxysql_status),
136+
readyset_status: ReadysetStatus::Unknown,
93137
conn: Some(conn),
94138
}
95139
}
@@ -112,31 +156,40 @@ impl Host {
112156
self.port
113157
}
114158

115-
/// Gets the status of the host.
159+
/// Gets the proxysql status of the host.
116160
///
117161
/// # Returns
118162
///
119163
/// The status of the host.
120-
pub fn get_status(&self) -> HostStatus {
121-
self.status
164+
pub fn get_proxysql_status(&self) -> ProxyStatus {
165+
self.proxysql_status
122166
}
123167

124-
/// Changes the status of the host.
168+
/// Changes the proxysql status of the host.
125169
///
126170
/// # Arguments
127171
///
128172
/// * `status` - The new status of the host.
129-
pub fn change_status(&mut self, status: HostStatus) {
130-
self.status = status;
173+
pub fn change_proxysql_status(&mut self, status: ProxyStatus) {
174+
self.proxysql_status = status;
131175
}
132176

133-
/// Checks if the host is online.
177+
/// Checks if the host is online in proxysql.
134178
///
135179
/// # Returns
136180
///
137181
/// true if the host is online, false otherwise.
138-
pub fn is_online(&self) -> bool {
139-
self.status == HostStatus::Online
182+
pub fn is_proxysql_online(&self) -> bool {
183+
self.proxysql_status == ProxyStatus::Online
184+
}
185+
186+
/// Gets the readyset status of the host.
187+
///
188+
/// # Returns
189+
///
190+
/// The status of the host.
191+
pub fn get_readyset_status(&self) -> ReadysetStatus {
192+
self.readyset_status
140193
}
141194

142195
/// Checks if the Readyset host is ready to serve traffic.
@@ -145,19 +198,28 @@ impl Host {
145198
/// # Returns
146199
///
147200
/// true if the host is ready, false otherwise.
148-
pub fn check_readyset_is_ready(&mut self) -> Result<bool, mysql::Error> {
201+
pub fn check_readyset_is_ready(&mut self) -> Result<ProxyStatus, mysql::Error> {
149202
match &mut self.conn {
150203
Some(conn) => {
151204
let result = conn.query("SHOW READYSET STATUS");
152205
match result {
153206
Ok(rows) => {
154207
let rows: Vec<(String, String)> = rows;
155208
for (field, value) in rows {
156-
if field == "Snapshot Status" {
157-
return Ok(value == "Completed");
209+
if field == "Snapshot Status" && value == "Completed" {
210+
self.readyset_status = ReadysetStatus::Online;
211+
return Ok(ProxyStatus::Online);
212+
} else if field == "Snapshot Status" && value == "In Progress" {
213+
self.readyset_status = ReadysetStatus::SnapshotInProgress;
214+
return Ok(ProxyStatus::Shunned);
215+
} else if field == "Status" {
216+
let status = ReadysetStatus::from(value);
217+
self.readyset_status = status;
218+
return Ok(status.into());
158219
}
159220
}
160-
Ok(false)
221+
self.readyset_status = ReadysetStatus::Unknown;
222+
Ok(ProxyStatus::Shunned)
161223
}
162224
Err(err) => Err(mysql::Error::IoError(std::io::Error::new(
163225
std::io::ErrorKind::Other,

src/proxysql.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use mysql::{prelude::Queryable, Conn, OptsBuilder};
33

44
use crate::{
55
config,
6-
hosts::{Host, HostStatus},
6+
hosts::{Host, ProxyStatus},
77
messages,
88
queries::Query,
99
};
@@ -40,7 +40,7 @@ impl ProxySQL {
4040
.expect("Failed to create ProxySQL connection");
4141

4242
let query = format!(
43-
"SELECT hostname, port, status, comment FROM mysql_servers WHERE hostgroup_id = {} AND status IN ('ONLINE', 'SHUNNED')",
43+
"SELECT hostname, port, status, comment FROM mysql_servers WHERE hostgroup_id = {} AND status IN ('ONLINE', 'SHUNNED', 'OFFLINE_SOFT')",
4444
config.readyset_hostgroup
4545
);
4646
let results: Vec<(String, u16, String, String)> = conn.query(query).unwrap();
@@ -176,23 +176,29 @@ impl ProxySQL {
176176

177177
for host in self.hosts.iter_mut() {
178178
match host.check_readyset_is_ready() {
179-
Ok(ready) => {
180-
if ready {
181-
status_changes.push((host, HostStatus::Online));
182-
} else {
183-
messages::print_note("Readyset is still running Snapshot.");
184-
status_changes.push((host, HostStatus::Shunned));
179+
Ok(ready) => match ready {
180+
ProxyStatus::Online => {
181+
status_changes.push((host, ProxyStatus::Online));
185182
}
186-
}
183+
ProxyStatus::Shunned => {
184+
status_changes.push((host, ProxyStatus::Shunned));
185+
}
186+
ProxyStatus::OfflineSoft => {
187+
status_changes.push((host, ProxyStatus::OfflineSoft));
188+
}
189+
ProxyStatus::OfflineHard => {
190+
status_changes.push((host, ProxyStatus::OfflineHard));
191+
}
192+
},
187193
Err(e) => {
188194
messages::print_error(format!("Cannot check Readyset status: {}.", e).as_str());
189-
status_changes.push((host, HostStatus::Shunned));
195+
status_changes.push((host, ProxyStatus::Shunned));
190196
}
191197
};
192198
}
193199

194200
for (host, status) in status_changes {
195-
if host.get_status() != status {
201+
if host.get_proxysql_status() != status {
196202
let where_clause = format!(
197203
"WHERE hostgroup_id = {} AND hostname = '{}' AND port = {}",
198204
self.readyset_hostgroup,
@@ -201,23 +207,24 @@ impl ProxySQL {
201207
);
202208
messages::print_note(
203209
format!(
204-
"Server HG: {}, Host: {}, Port: {} is currently {}. Changing to {}",
210+
"Server HG: {}, Host: {}, Port: {} is currently {} on proxysql and {} on readyset. Changing to {}",
205211
self.readyset_hostgroup,
206212
host.get_hostname(),
207213
host.get_port(),
208-
host.get_status(),
214+
host.get_proxysql_status(),
215+
host.get_readyset_status().to_string().to_uppercase(),
209216
status
210217
)
211218
.as_str(),
212219
);
213-
host.change_status(status);
220+
host.change_proxysql_status(status);
214221
if self.dry_run {
215222
messages::print_info("Dry run, skipping changes to ProxySQL");
216223
continue;
217224
}
218225
let _ = self.conn.query_drop(format!(
219226
"UPDATE mysql_servers SET status = '{}' {}",
220-
host.get_status(),
227+
host.get_proxysql_status(),
221228
where_clause
222229
));
223230
let _ = self.conn.query_drop("LOAD MYSQL SERVERS TO RUNTIME");
@@ -235,7 +242,7 @@ impl ProxySQL {
235242
pub fn number_of_online_hosts(&self) -> u16 {
236243
self.hosts
237244
.iter()
238-
.filter(|host| host.is_online())
245+
.filter(|host| host.is_proxysql_online())
239246
.collect::<Vec<&Host>>()
240247
.len() as u16
241248
}
@@ -247,7 +254,7 @@ impl ProxySQL {
247254
///
248255
/// An Option containing a reference to the first online host.
249256
pub fn get_first_online_host(&mut self) -> Option<&mut Host> {
250-
self.hosts.iter_mut().find(|host| host.is_online())
257+
self.hosts.iter_mut().find(|host| host.is_proxysql_online())
251258
}
252259

253260
/// This function is used to get all the online hosts.
@@ -259,7 +266,7 @@ impl ProxySQL {
259266
pub fn get_online_hosts(&mut self) -> Vec<&mut Host> {
260267
self.hosts
261268
.iter_mut()
262-
.filter(|host| host.is_online())
269+
.filter(|host| host.is_proxysql_online())
263270
.collect()
264271
}
265272
}

0 commit comments

Comments
 (0)