mirror of https://github.com/mastodon/flodgatt
Refacto RedisConn [WIP]
This commit is contained in:
parent
829d193ec3
commit
eaa308b3eb
|
@ -5,7 +5,7 @@ use flodgatt::request::{Handler, Subscription, Timeline};
|
||||||
use flodgatt::response::redis;
|
use flodgatt::response::redis;
|
||||||
use flodgatt::response::stream;
|
use flodgatt::response::stream;
|
||||||
|
|
||||||
use futures::{future::lazy, stream::Stream as _Stream};
|
use futures::{future::lazy, stream::Stream as _};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
mod err;
|
mod err;
|
||||||
pub use err::RedisConnErr;
|
pub use err::RedisConnErr;
|
||||||
|
|
||||||
use super::msg::{RedisParseErr, RedisParseOutput};
|
use super::msg::{RedisMsg, RedisParseErr, RedisParseOutput};
|
||||||
use super::ManagerErr;
|
use super::ManagerErr;
|
||||||
use crate::config::Redis;
|
use crate::config::Redis;
|
||||||
use crate::event::Event;
|
use crate::event::Event;
|
||||||
use crate::request::{Stream, Timeline};
|
use crate::request::{Stream, Timeline};
|
||||||
use futures::{Async, Poll};
|
|
||||||
|
use futures::Async;
|
||||||
use lru::LruCache;
|
use lru::LruCache;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
@ -15,6 +16,7 @@ use std::str;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
type Result<T> = std::result::Result<T, RedisConnErr>;
|
type Result<T> = std::result::Result<T, RedisConnErr>;
|
||||||
|
type Poll = futures::Poll<Option<(Timeline, Event)>, ManagerErr>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RedisConn {
|
pub struct RedisConn {
|
||||||
|
@ -46,15 +48,12 @@ impl RedisConn {
|
||||||
Ok(redis_conn)
|
Ok(redis_conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_redis(&mut self) -> Poll<Option<(Timeline, Event)>, ManagerErr> {
|
pub fn poll_redis(&mut self) -> Poll {
|
||||||
let mut size = 100; // large enough to handle subscribe/unsubscribe notice
|
let mut size = 100; // large enough to handle subscribe/unsubscribe notice
|
||||||
let (mut buffer, mut first_read) = (vec![0u8; size], true);
|
let (mut buffer, mut first_read) = (vec![0u8; size], true);
|
||||||
loop {
|
loop {
|
||||||
match self.primary.read(&mut buffer) {
|
match self.primary.read(&mut buffer) {
|
||||||
Ok(n) if n != size => {
|
Ok(n) if n != size => break self.redis_input.extend_from_slice(&buffer[..n]),
|
||||||
self.redis_input.extend_from_slice(&buffer[..n]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Ok(n) => self.redis_input.extend_from_slice(&buffer[..n]),
|
Ok(n) => self.redis_input.extend_from_slice(&buffer[..n]),
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
};
|
};
|
||||||
|
@ -68,6 +67,7 @@ impl RedisConn {
|
||||||
if self.redis_input.is_empty() {
|
if self.redis_input.is_empty() {
|
||||||
return Ok(Async::NotReady);
|
return Ok(Async::NotReady);
|
||||||
}
|
}
|
||||||
|
|
||||||
let input = self.redis_input.clone();
|
let input = self.redis_input.clone();
|
||||||
self.redis_input.clear();
|
self.redis_input.clear();
|
||||||
|
|
||||||
|
@ -82,16 +82,12 @@ impl RedisConn {
|
||||||
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(&format!("{}:timeline:", ns)) => {
|
||||||
let trimmed_tl_txt = &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_txt, &mut self.tag_id_cache)?;
|
(self.into_tl_event(trimmed_tl, &msg)?, msg.leftover_input)
|
||||||
let event = msg.event_txt.try_into()?;
|
|
||||||
(Ok(Ready(Some((tl, event)))), msg.leftover_input)
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let trimmed_tl_txt = &msg.timeline_txt["timeline:".len()..];
|
let trimmed_tl = &msg.timeline_txt["timeline:".len()..];
|
||||||
let tl = Timeline::from_redis_text(trimmed_tl_txt, &mut self.tag_id_cache)?;
|
(self.into_tl_event(trimmed_tl, &msg)?, msg.leftover_input)
|
||||||
let event = msg.event_txt.try_into()?;
|
|
||||||
(Ok(Ready(Some((tl, event)))), msg.leftover_input)
|
|
||||||
}
|
}
|
||||||
Some(_non_matching_namespace) => (Ok(Ready(None)), msg.leftover_input),
|
Some(_non_matching_namespace) => (Ok(Ready(None)), msg.leftover_input),
|
||||||
},
|
},
|
||||||
|
@ -104,6 +100,12 @@ impl RedisConn {
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn into_tl_event<'a>(&mut self, tl: &'a str, msg: &'a RedisMsg) -> Result<Poll> {
|
||||||
|
let tl = Timeline::from_redis_text(tl, &mut self.tag_id_cache)?;
|
||||||
|
let event = msg.event_txt.try_into().expect("TODO");
|
||||||
|
Ok(Ok(Async::Ready(Some((tl, event)))))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_cache(&mut self, hashtag: String, id: i64) {
|
pub fn update_cache(&mut self, hashtag: String, id: i64) {
|
||||||
self.tag_id_cache.put(hashtag.clone(), id);
|
self.tag_id_cache.put(hashtag.clone(), id);
|
||||||
self.tag_name_cache.put(id, hashtag);
|
self.tag_name_cache.put(id, hashtag);
|
||||||
|
@ -116,18 +118,9 @@ impl RedisConn {
|
||||||
};
|
};
|
||||||
|
|
||||||
let tl = timeline.to_redis_raw_timeline(hashtag)?;
|
let tl = timeline.to_redis_raw_timeline(hashtag)?;
|
||||||
let (primary_cmd, secondary_cmd) = match cmd {
|
let (primary_cmd, secondary_cmd) = cmd.into_sendable(&tl);
|
||||||
RedisCmd::Subscribe => (
|
self.primary.write_all(&primary_cmd)?;
|
||||||
format!("*2\r\n$9\r\nsubscribe\r\n${}\r\n{}\r\n", tl.len(), tl),
|
self.secondary.write_all(&secondary_cmd)?;
|
||||||
format!("*3\r\n$3\r\nSET\r\n${}\r\n{}\r\n$1\r\n1\r\n", tl.len(), tl),
|
|
||||||
),
|
|
||||||
RedisCmd::Unsubscribe => (
|
|
||||||
format!("*2\r\n$11\r\nunsubscribe\r\n${}\r\n{}\r\n", tl.len(), tl),
|
|
||||||
format!("*3\r\n$3\r\nSET\r\n${}\r\n{}\r\n$1\r\n0\r\n", tl.len(), tl),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
self.primary.write_all(&primary_cmd.as_bytes())?;
|
|
||||||
self.secondary.write_all(&secondary_cmd.as_bytes())?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,3 +167,18 @@ pub enum RedisCmd {
|
||||||
Subscribe,
|
Subscribe,
|
||||||
Unsubscribe,
|
Unsubscribe,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RedisCmd {
|
||||||
|
pub fn into_sendable(&self, tl: &String) -> (Vec<u8>, Vec<u8>) {
|
||||||
|
match self {
|
||||||
|
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(),
|
||||||
|
),
|
||||||
|
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(),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,9 +28,8 @@ pub struct Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
/// Create a new `Receiver`, with its own Redis connections (but, as yet, no
|
/// Create a new `Manager`, with its own Redis connections (but, as yet, no
|
||||||
/// active subscriptions).
|
/// active subscriptions).
|
||||||
|
|
||||||
pub fn try_from(
|
pub fn try_from(
|
||||||
redis_cfg: config::Redis,
|
redis_cfg: config::Redis,
|
||||||
tx: watch::Sender<(Timeline, Event)>,
|
tx: watch::Sender<(Timeline, Event)>,
|
||||||
|
@ -38,7 +37,6 @@ impl Manager {
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
redis_connection: RedisConn::new(redis_cfg)?,
|
redis_connection: RedisConn::new(redis_cfg)?,
|
||||||
|
|
||||||
clients_per_timeline: HashMap::new(),
|
clients_per_timeline: HashMap::new(),
|
||||||
tx,
|
tx,
|
||||||
rx,
|
rx,
|
||||||
|
|
Loading…
Reference in New Issue