-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
dynamic creation of stores based on url
- Loading branch information
1 parent
7b973e2
commit 8617e5e
Showing
6 changed files
with
126 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
use super::{Error, Result, Route, Store, StoreFactory}; | ||
use std::pin::Pin; | ||
|
||
use super::{Error, Result, Route, Store}; | ||
use anyhow::Context; | ||
|
||
use bb8_redis::{ | ||
|
@@ -9,6 +11,7 @@ use bb8_redis::{ | |
}, | ||
RedisConnectionManager, | ||
}; | ||
use futures::Future; | ||
|
||
#[derive(Debug)] | ||
struct WithNamespace { | ||
|
@@ -40,63 +43,61 @@ impl CustomizeConnection<Connection, RedisError> for WithNamespace { | |
|
||
pub struct ZdbStoreFactory; | ||
|
||
impl ZdbStoreFactory { | ||
fn get_connection_info<U: AsRef<str>>(&self, u: U) -> Result<(ConnectionInfo, Option<String>)> { | ||
let u = url::Url::parse(u.as_ref())?; | ||
|
||
let (address, namespace) = match u.host() { | ||
Some(host) => { | ||
let addr = ConnectionAddr::Tcp(host.to_string(), u.port().unwrap_or(9900)); | ||
let ns: Option<String> = u | ||
.path_segments() | ||
.and_then(|s| s.last().map(|s| s.to_owned())); | ||
(addr, ns) | ||
} | ||
None => (ConnectionAddr::Unix(u.path().into()), None), | ||
}; | ||
|
||
Ok(( | ||
ConnectionInfo { | ||
addr: address, | ||
redis: RedisConnectionInfo { | ||
db: 0, | ||
username: if u.username().is_empty() { | ||
None | ||
} else { | ||
Some(u.username().into()) | ||
}, | ||
password: u.password().map(|s| s.into()), | ||
fn get_connection_info<U: AsRef<str>>(u: U) -> Result<(ConnectionInfo, Option<String>)> { | ||
let u = url::Url::parse(u.as_ref())?; | ||
|
||
let (address, namespace) = match u.host() { | ||
Some(host) => { | ||
let addr = ConnectionAddr::Tcp(host.to_string(), u.port().unwrap_or(9900)); | ||
let ns: Option<String> = u | ||
.path_segments() | ||
.and_then(|s| s.last().map(|s| s.to_owned())); | ||
(addr, ns) | ||
} | ||
None => (ConnectionAddr::Unix(u.path().into()), None), | ||
}; | ||
|
||
Ok(( | ||
ConnectionInfo { | ||
addr: address, | ||
redis: RedisConnectionInfo { | ||
db: 0, | ||
username: if u.username().is_empty() { | ||
None | ||
} else { | ||
Some(u.username().into()) | ||
}, | ||
password: u.password().map(|s| s.into()), | ||
}, | ||
namespace, | ||
)) | ||
} | ||
}, | ||
namespace, | ||
)) | ||
} | ||
|
||
#[async_trait::async_trait] | ||
impl StoreFactory for ZdbStoreFactory { | ||
type Store = ZdbStore; | ||
async fn make_inner(url: String) -> Result<Box<dyn Store>> { | ||
let (mut info, namespace) = get_connection_info(&url)?; | ||
|
||
async fn build<U: AsRef<str> + Send>(&self, u: U) -> anyhow::Result<Self::Store> { | ||
let url = u.as_ref().to_owned(); | ||
let (mut info, namespace) = self.get_connection_info(u)?; | ||
let namespace = WithNamespace { | ||
namespace, | ||
password: info.redis.password.take(), | ||
}; | ||
|
||
let namespace = WithNamespace { | ||
namespace, | ||
password: info.redis.password.take(), | ||
}; | ||
log::debug!("switching namespace to: {:?}", namespace.namespace); | ||
let mgr = | ||
RedisConnectionManager::new(info).context("failed to create redis connection manager")?; | ||
|
||
log::debug!("switching namespace to: {:?}", namespace.namespace); | ||
let mgr = RedisConnectionManager::new(info)?; | ||
let pool = Pool::builder() | ||
.max_size(20) | ||
.connection_customizer(Box::new(namespace)) | ||
.build(mgr) | ||
.await | ||
.context("failed to create connection pool")?; | ||
|
||
let pool = Pool::builder() | ||
.max_size(20) | ||
.connection_customizer(Box::new(namespace)) | ||
.build(mgr) | ||
.await?; | ||
Ok(Box::from(ZdbStore { url, pool })) | ||
} | ||
|
||
Ok(ZdbStore { url, pool }) | ||
} | ||
pub fn make(url: &str) -> Pin<Box<dyn Future<Output = Result<Box<dyn Store>>>>> { | ||
Box::pin(make_inner(url.into())) | ||
} | ||
|
||
#[derive(Clone)] | ||
|
@@ -141,28 +142,22 @@ mod test { | |
|
||
#[test] | ||
fn test_connection_info_simple() { | ||
let (info, ns) = ZdbStoreFactory | ||
.get_connection_info("zdb://hub.grid.tf:9900") | ||
.unwrap(); | ||
let (info, ns) = get_connection_info("zdb://hub.grid.tf:9900").unwrap(); | ||
assert_eq!(ns, None); | ||
assert_eq!(info.addr, ConnectionAddr::Tcp("hub.grid.tf".into(), 9900)); | ||
} | ||
|
||
#[test] | ||
fn test_connection_info_ns() { | ||
let (info, ns) = ZdbStoreFactory | ||
.get_connection_info("zdb://[email protected]/custom") | ||
.unwrap(); | ||
let (info, ns) = get_connection_info("zdb://[email protected]/custom").unwrap(); | ||
assert_eq!(ns, Some("custom".into())); | ||
assert_eq!(info.addr, ConnectionAddr::Tcp("hub.grid.tf".into(), 9900)); | ||
assert_eq!(info.redis.username, Some("username".into())); | ||
} | ||
|
||
#[test] | ||
fn test_connection_info_unix() { | ||
let (info, ns) = ZdbStoreFactory | ||
.get_connection_info("zdb:///path/to/socket") | ||
.unwrap(); | ||
let (info, ns) = get_connection_info("zdb:///path/to/socket").unwrap(); | ||
assert_eq!(ns, None); | ||
assert_eq!(info.addr, ConnectionAddr::Unix("/path/to/socket".into())); | ||
} | ||
|