-
Notifications
You must be signed in to change notification settings - Fork 221
Allow configuring routing decision when no shard is selected #578
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
75836da
425a216
7f69133
b48c08e
3ab8424
f6ae499
39674bc
433bf6e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,11 +3,14 @@ use arc_swap::ArcSwap; | |
use log::{error, info}; | ||
use once_cell::sync::Lazy; | ||
use regex::Regex; | ||
use serde::{Deserializer, Serializer}; | ||
use serde_derive::{Deserialize, Serialize}; | ||
|
||
use std::collections::hash_map::DefaultHasher; | ||
use std::collections::{BTreeMap, HashMap, HashSet}; | ||
use std::hash::{Hash, Hasher}; | ||
use std::path::Path; | ||
use std::sync::atomic::{AtomicU64, Ordering}; | ||
use std::sync::Arc; | ||
use tokio::fs::File; | ||
use tokio::io::AsyncReadExt; | ||
|
@@ -101,6 +104,9 @@ pub struct Address { | |
|
||
/// Address stats | ||
pub stats: Arc<AddressStats>, | ||
|
||
/// Number of errors encountered since last successful checkout | ||
pub error_count: Arc<AtomicU64>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we show this in admin? This would be a really cool metric to expose. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't be too difficult to expose it. It gets reset with every successful checkout so I am not sure how useful it would be. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I see. Not so useful then, unless the replica is banned? Could be useful to see how many errors it took before it got successfully banned. Alternatively, we don't reset that number? If it's an i64, it can be incremented ...forever without worrying about overflows. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought about not resetting it too but that meant errors that occurred 2 days ago can affect routing decisions today There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. |
||
} | ||
|
||
impl Default for Address { | ||
|
@@ -118,6 +124,7 @@ impl Default for Address { | |
pool_name: String::from("pool_name"), | ||
mirrors: Vec::new(), | ||
stats: Arc::new(AddressStats::default()), | ||
error_count: Arc::new(AtomicU64::new(0)), | ||
} | ||
} | ||
} | ||
|
@@ -182,6 +189,18 @@ impl Address { | |
), | ||
} | ||
} | ||
|
||
pub fn error_count(&self) -> u64 { | ||
self.error_count.load(Ordering::Relaxed) | ||
} | ||
|
||
pub fn increment_error_count(&self) { | ||
self.error_count.fetch_add(1, Ordering::Relaxed); | ||
} | ||
|
||
pub fn reset_error_count(&self) { | ||
self.error_count.store(0, Ordering::Relaxed); | ||
} | ||
} | ||
|
||
/// PostgreSQL user. | ||
|
@@ -540,6 +559,9 @@ pub struct Pool { | |
pub shard_id_regex: Option<String>, | ||
pub regex_search_limit: Option<usize>, | ||
|
||
#[serde(default = "Pool::default_default_shard")] | ||
pub default_shard: DefaultShard, | ||
|
||
pub auth_query: Option<String>, | ||
pub auth_query_user: Option<String>, | ||
pub auth_query_password: Option<String>, | ||
|
@@ -575,6 +597,10 @@ impl Pool { | |
PoolMode::Transaction | ||
} | ||
|
||
pub fn default_default_shard() -> DefaultShard { | ||
DefaultShard::default() | ||
} | ||
|
||
pub fn default_load_balancing_mode() -> LoadBalancingMode { | ||
LoadBalancingMode::Random | ||
} | ||
|
@@ -666,6 +692,16 @@ impl Pool { | |
None => None, | ||
}; | ||
|
||
match self.default_shard { | ||
DefaultShard::Shard(shard_number) => { | ||
if shard_number >= self.shards.len() { | ||
error!("Invalid shard {:?}", shard_number); | ||
return Err(Error::BadConfig); | ||
} | ||
} | ||
_ => (), | ||
} | ||
|
||
for (_, user) in &self.users { | ||
user.validate()?; | ||
} | ||
|
@@ -693,6 +729,7 @@ impl Default for Pool { | |
sharding_key_regex: None, | ||
shard_id_regex: None, | ||
regex_search_limit: Some(1000), | ||
default_shard: Self::default_default_shard(), | ||
auth_query: None, | ||
auth_query_user: None, | ||
auth_query_password: None, | ||
|
@@ -711,6 +748,50 @@ pub struct ServerConfig { | |
pub role: Role, | ||
} | ||
|
||
// No Shard Specified handling. | ||
#[derive(Debug, PartialEq, Clone, Eq, Hash, Copy)] | ||
pub enum DefaultShard { | ||
Shard(usize), | ||
Random, | ||
RandomHealthy, | ||
} | ||
impl Default for DefaultShard { | ||
fn default() -> Self { | ||
DefaultShard::Shard(0) | ||
} | ||
} | ||
impl serde::Serialize for DefaultShard { | ||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { | ||
match self { | ||
DefaultShard::Shard(shard) => { | ||
serializer.serialize_str(&format!("shard_{}", &shard.to_string())) | ||
} | ||
DefaultShard::Random => serializer.serialize_str("random"), | ||
DefaultShard::RandomHealthy => serializer.serialize_str("random_healthy"), | ||
} | ||
} | ||
} | ||
impl<'de> serde::Deserialize<'de> for DefaultShard { | ||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
where | ||
D: Deserializer<'de>, | ||
{ | ||
let s = String::deserialize(deserializer)?; | ||
if s.starts_with("shard_") { | ||
let shard = s[6..].parse::<usize>().map_err(serde::de::Error::custom)?; | ||
return Ok(DefaultShard::Shard(shard)); | ||
} | ||
|
||
match s.as_str() { | ||
"random" => Ok(DefaultShard::Random), | ||
"random_healthy" => Ok(DefaultShard::RandomHealthy), | ||
_ => Err(serde::de::Error::custom( | ||
"invalid value for no_shard_specified_behavior", | ||
)), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, Hash, Eq)] | ||
pub struct MirrorServerConfig { | ||
pub host: String, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug output going to the client here.