mirror of https://github.com/mastodon/flodgatt
Remove `format!` calls from hot path
This commit is contained in:
parent
e100f5760a
commit
8fcd040f21
|
@ -19,25 +19,29 @@ impl Timeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_redis_raw_timeline(&self, hashtag: Option<&String>) -> Result<String> {
|
pub fn to_redis_raw_timeline(&self, hashtag: Option<&String>) -> Result<String> {
|
||||||
use {Content::*, Reach::*, Stream::*};
|
// TODO -- does this need to account for namespaces?
|
||||||
|
use {Content::*, Reach::*, Stream::*, TimelineErr::*};
|
||||||
|
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
Timeline(Public, Federated, All) => "timeline:public".into(),
|
Timeline(Public, Federated, All) => "timeline:public".to_string(),
|
||||||
Timeline(Public, Local, All) => "timeline:public:local".into(),
|
Timeline(Public, Local, All) => "timeline:public:local".to_string(),
|
||||||
Timeline(Public, Federated, Media) => "timeline:public:media".into(),
|
Timeline(Public, Federated, Media) => "timeline:public:media".to_string(),
|
||||||
Timeline(Public, Local, Media) => "timeline:public:local:media".into(),
|
Timeline(Public, Local, Media) => "timeline:public:local:media".to_string(),
|
||||||
// TODO -- would `.push_str` be faster here?
|
Timeline(Hashtag(_id), Federated, All) => {
|
||||||
Timeline(Hashtag(_id), Federated, All) => format!(
|
["timeline:hashtag:", hashtag.ok_or(MissingHashtag)?].concat()
|
||||||
"timeline:hashtag:{}",
|
}
|
||||||
hashtag.ok_or(TimelineErr::MissingHashtag)?
|
Timeline(Hashtag(_id), Local, All) => [
|
||||||
),
|
"timeline:hashtag:",
|
||||||
Timeline(Hashtag(_id), Local, All) => format!(
|
hashtag.ok_or(MissingHashtag)?,
|
||||||
"timeline:hashtag:{}:local",
|
":local",
|
||||||
hashtag.ok_or(TimelineErr::MissingHashtag)?
|
]
|
||||||
),
|
.concat(),
|
||||||
Timeline(User(id), Federated, All) => format!("timeline:{}", id),
|
Timeline(User(id), Federated, All) => ["timeline:", &id.to_string()].concat(),
|
||||||
Timeline(User(id), Federated, Notification) => format!("timeline:{}:notification", id),
|
Timeline(User(id), Federated, Notification) => {
|
||||||
Timeline(List(id), Federated, All) => format!("timeline:list:{}", id),
|
["timeline:", &id.to_string(), ":notification"].concat()
|
||||||
Timeline(Direct(id), Federated, All) => format!("timeline:direct:{}", id),
|
}
|
||||||
|
Timeline(List(id), Federated, All) => ["timeline:list:", &id.to_string()].concat(),
|
||||||
|
Timeline(Direct(id), Federated, All) => ["timeline:direct:", &id.to_string()].concat(),
|
||||||
Timeline(_one, _two, _three) => Err(TimelineErr::InvalidInput)?,
|
Timeline(_one, _two, _three) => Err(TimelineErr::InvalidInput)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -57,8 +61,7 @@ impl Timeline {
|
||||||
[id, "notification"] => Timeline(User(id.parse()?), Federated, Notification),
|
[id, "notification"] => Timeline(User(id.parse()?), Federated, Notification),
|
||||||
["list", id] => Timeline(List(id.parse()?), Federated, All),
|
["list", id] => Timeline(List(id.parse()?), Federated, All),
|
||||||
["direct", id] => Timeline(Direct(id.parse()?), Federated, All),
|
["direct", id] => Timeline(Direct(id.parse()?), Federated, All),
|
||||||
// Other endpoints don't exist:
|
[..] => Err(InvalidInput)?, // Other endpoints don't exist
|
||||||
[..] => Err(InvalidInput)?,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,40 @@ impl RedisCmd {
|
||||||
pub fn into_sendable(self, tl: &str) -> (Vec<u8>, Vec<u8>) {
|
pub fn into_sendable(self, tl: &str) -> (Vec<u8>, Vec<u8>) {
|
||||||
match self {
|
match self {
|
||||||
RedisCmd::Subscribe => (
|
RedisCmd::Subscribe => (
|
||||||
format!("*2\r\n$9\r\nsubscribe\r\n${}\r\n{}\r\n", tl.len(), tl).into_bytes(),
|
[
|
||||||
format!("*3\r\n$3\r\nSET\r\n${}\r\n{}\r\n$1\r\n1\r\n", tl.len(), tl).into_bytes(),
|
b"*2\r\n$9\r\nsubscribe\r\n$",
|
||||||
|
tl.len().to_string().as_bytes(),
|
||||||
|
b"\r\n",
|
||||||
|
tl.as_bytes(),
|
||||||
|
b"\r\n",
|
||||||
|
]
|
||||||
|
.concat(),
|
||||||
|
[
|
||||||
|
b"*3\r\n$3\r\nSET\r\n$",
|
||||||
|
tl.len().to_string().as_bytes(),
|
||||||
|
b"\r\n",
|
||||||
|
tl.as_bytes(),
|
||||||
|
b"\r\n$1\r\n1\r\n",
|
||||||
|
]
|
||||||
|
.concat(),
|
||||||
),
|
),
|
||||||
RedisCmd::Unsubscribe => (
|
RedisCmd::Unsubscribe => (
|
||||||
format!("*2\r\n$11\r\nunsubscribe\r\n${}\r\n{}\r\n", tl.len(), tl).into_bytes(),
|
[
|
||||||
format!("*3\r\n$3\r\nSET\r\n${}\r\n{}\r\n$1\r\n0\r\n", tl.len(), tl).into_bytes(),
|
b"*2\r\n$11\r\nunsubscribe\r\n$",
|
||||||
|
tl.len().to_string().as_bytes(),
|
||||||
|
b"\r\n",
|
||||||
|
tl.as_bytes(),
|
||||||
|
b"\r\n",
|
||||||
|
]
|
||||||
|
.concat(),
|
||||||
|
[
|
||||||
|
b"*3\r\n$3\r\nSET\r\n$",
|
||||||
|
tl.len().to_string().as_bytes(),
|
||||||
|
b"\r\n",
|
||||||
|
tl.as_bytes(),
|
||||||
|
b"\r\n$1\r\n0\r\n",
|
||||||
|
]
|
||||||
|
.concat(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,8 @@ pub struct RedisConn {
|
||||||
|
|
||||||
impl RedisConn {
|
impl RedisConn {
|
||||||
pub fn new(redis_cfg: &Redis) -> Result<Self> {
|
pub fn new(redis_cfg: &Redis) -> Result<Self> {
|
||||||
let addr = format!("{}:{}", *redis_cfg.host, *redis_cfg.port);
|
let addr = [&*redis_cfg.host, ":", &*redis_cfg.port.to_string()].concat();
|
||||||
|
|
||||||
let conn = Self::new_connection(&addr, redis_cfg.password.as_ref())?;
|
let conn = Self::new_connection(&addr, redis_cfg.password.as_ref())?;
|
||||||
conn.set_nonblocking(true)
|
conn.set_nonblocking(true)
|
||||||
.map_err(|e| RedisConnErr::with_addr(&addr, e))?;
|
.map_err(|e| RedisConnErr::with_addr(&addr, e))?;
|
||||||
|
@ -81,7 +82,7 @@ impl RedisConn {
|
||||||
use {Async::*, RedisParseOutput::*};
|
use {Async::*, RedisParseOutput::*};
|
||||||
let (res, leftover) = match RedisParseOutput::try_from(input) {
|
let (res, leftover) = match RedisParseOutput::try_from(input) {
|
||||||
Ok(Msg(msg)) => match &self.redis_namespace {
|
Ok(Msg(msg)) => match &self.redis_namespace {
|
||||||
Some(ns) if msg.timeline_txt.starts_with(&format!("{}:timeline:", ns)) => {
|
Some(ns) if msg.timeline_txt.starts_with(&[ns, ":timeline:"].concat()) => {
|
||||||
let trimmed_tl = &msg.timeline_txt[ns.len() + ":timeline:".len()..];
|
let trimmed_tl = &msg.timeline_txt[ns.len() + ":timeline:".len()..];
|
||||||
let tl = Timeline::from_redis_text(trimmed_tl, &mut self.tag_id_cache)?;
|
let tl = Timeline::from_redis_text(trimmed_tl, &mut self.tag_id_cache)?;
|
||||||
let event = msg.event_txt.try_into()?;
|
let event = msg.event_txt.try_into()?;
|
||||||
|
@ -135,8 +136,17 @@ impl RedisConn {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn auth_connection(conn: &mut TcpStream, addr: &str, pass: &str) -> Result<()> {
|
fn auth_connection(conn: &mut TcpStream, addr: &str, pass: &str) -> Result<()> {
|
||||||
conn.write_all(&format!("*2\r\n$4\r\nauth\r\n${}\r\n{}\r\n", pass.len(), pass).as_bytes())
|
conn.write_all(
|
||||||
.map_err(|e| RedisConnErr::with_addr(&addr, e))?;
|
&[
|
||||||
|
b"*2\r\n$4\r\nauth\r\n$",
|
||||||
|
pass.len().to_string().as_bytes(),
|
||||||
|
b"\r\n",
|
||||||
|
pass.as_bytes(),
|
||||||
|
b"\r\n",
|
||||||
|
]
|
||||||
|
.concat(),
|
||||||
|
)
|
||||||
|
.map_err(|e| RedisConnErr::with_addr(&addr, e))?;
|
||||||
let mut buffer = vec![0_u8; 5];
|
let mut buffer = vec![0_u8; 5];
|
||||||
conn.read_exact(&mut buffer)
|
conn.read_exact(&mut buffer)
|
||||||
.map_err(|e| RedisConnErr::with_addr(&addr, e))?;
|
.map_err(|e| RedisConnErr::with_addr(&addr, e))?;
|
||||||
|
|
|
@ -82,10 +82,7 @@ fn utf8_to_redis_data<'a>(s: &'a str) -> Result<(RedisData, &'a str), RedisParse
|
||||||
":" => parse_redis_int(s),
|
":" => parse_redis_int(s),
|
||||||
"$" => parse_redis_bulk_string(s),
|
"$" => parse_redis_bulk_string(s),
|
||||||
"*" => parse_redis_array(s),
|
"*" => parse_redis_array(s),
|
||||||
e => Err(InvalidLineStart(format!(
|
e => Err(InvalidLineStart(e.to_string())),
|
||||||
"Encountered invalid initial character `{}` in line `{}`",
|
|
||||||
e, s
|
|
||||||
))),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue