1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-01-18 05:41:50 +01:00

refactor pipeline impl

This commit is contained in:
Nikolay Kim 2018-01-10 16:45:57 -08:00
parent f7807e43d8
commit e0faf3f69c

View File

@ -34,6 +34,27 @@ enum PipelineState<S, H> {
Completed(Completed<S, H>),
}
impl<S: 'static, H: PipelineHandler<S>> PipelineState<S, H> {
fn is_response(&self) -> bool {
match *self {
PipelineState::Response(_) => true,
_ => false,
}
}
fn poll(&mut self, info: &mut PipelineInfo<S>) -> Option<PipelineState<S, H>> {
match *self {
PipelineState::Starting(ref mut state) => state.poll(info),
PipelineState::Handler(ref mut state) => state.poll(info),
PipelineState::RunMiddlewares(ref mut state) => state.poll(info),
PipelineState::Finishing(ref mut state) => state.poll(info),
PipelineState::Completed(ref mut state) => state.poll(info),
PipelineState::Response(_) | PipelineState::None | PipelineState::Error => None,
}
}
}
struct PipelineInfo<S> {
req: HttpRequest<S>,
count: usize,
@ -108,8 +129,7 @@ impl<S: 'static, H> Pipeline<S, H> {
PipelineState::None | PipelineState::Error
| PipelineState::Starting(_) | PipelineState::Handler(_)
| PipelineState::RunMiddlewares(_) | PipelineState::Response(_) => true,
PipelineState::Finishing(_) => self.0.context.is_none(),
PipelineState::Completed(_) => false,
PipelineState::Finishing(_) | PipelineState::Completed(_) => false,
}
}
}
@ -121,45 +141,13 @@ impl<S: 'static, H: PipelineHandler<S>> HttpHandlerTask for Pipeline<S, H> {
}
fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error> {
let info: &mut PipelineInfo<_> = unsafe{ mem::transmute(&mut self.0) };
loop {
if self.1.is_response() {
let state = mem::replace(&mut self.1, PipelineState::None);
match state {
PipelineState::None =>
return Ok(Async::Ready(true)),
PipelineState::Error =>
return Err(io::Error::new(io::ErrorKind::Other, "Internal error").into()),
PipelineState::Starting(st) => {
match st.poll(&mut self.0) {
Ok(state) =>
self.1 = state,
Err(state) => {
self.1 = state;
return Ok(Async::NotReady)
}
}
}
PipelineState::Handler(st) => {
match st.poll(&mut self.0) {
Ok(state) =>
self.1 = state,
Err(state) => {
self.1 = state;
return Ok(Async::NotReady)
}
}
}
PipelineState::RunMiddlewares(st) => {
match st.poll(&mut self.0) {
Ok(state) =>
self.1 = state,
Err(state) => {
self.1 = state;
return Ok(Async::NotReady)
}
}
}
PipelineState::Response(st) => {
match st.poll_io(io, &mut self.0) {
if let PipelineState::Response(st) = state {
match st.poll_io(io, info) {
Ok(state) => {
self.1 = state;
if let Some(error) = self.0.error.take() {
@ -170,100 +158,42 @@ impl<S: 'static, H: PipelineHandler<S>> HttpHandlerTask for Pipeline<S, H> {
}
Err(state) => {
self.1 = state;
return Ok(Async::NotReady)
return Ok(Async::NotReady);
}
}
}
PipelineState::Finishing(st) => {
match st.poll(&mut self.0) {
Ok(state) =>
self.1 = state,
Err(state) => {
self.1 = state;
return Ok(Async::NotReady)
}
}
}
PipelineState::Completed(st) => {
match st.poll(&mut self.0) {
Ok(state) => {
self.1 = state;
return Ok(Async::Ready(true));
}
Err(state) => {
self.1 = state;
return Ok(Async::NotReady)
}
}
match self.1 {
PipelineState::None =>
return Ok(Async::Ready(true)),
PipelineState::Error =>
return Err(io::Error::new(io::ErrorKind::Other, "Internal error").into()),
_ => (),
}
match self.1.poll(info) {
Some(state) => self.1 = state,
None => return Ok(Async::NotReady),
}
}
}
fn poll(&mut self) -> Poll<(), Error> {
let info: &mut PipelineInfo<_> = unsafe{ mem::transmute(&mut self.0) };
loop {
let state = mem::replace(&mut self.1, PipelineState::None);
match state {
match self.1 {
PipelineState::None | PipelineState::Error => {
return Ok(Async::Ready(()))
}
PipelineState::Starting(st) => {
match st.poll(&mut self.0) {
Ok(state) =>
self.1 = state,
Err(state) => {
self.1 = state;
return Ok(Async::NotReady)
}
}
}
PipelineState::Handler(st) => {
match st.poll(&mut self.0) {
Ok(state) =>
self.1 = state,
Err(state) => {
self.1 = state;
return Ok(Async::NotReady)
}
}
}
PipelineState::RunMiddlewares(st) => {
match st.poll(&mut self.0) {
Ok(state) =>
self.1 = state,
Err(state) => {
self.1 = state;
return Ok(Async::NotReady)
}
}
}
PipelineState::Response(_) => {
_ => (),
}
if let Some(state) = self.1.poll(info) {
self.1 = state;
} else {
return Ok(Async::NotReady);
}
PipelineState::Finishing(st) => {
match st.poll(&mut self.0) {
Ok(state) =>
self.1 = state,
Err(state) => {
self.1 = state;
return Ok(Async::NotReady)
}
}
}
PipelineState::Completed(st) => {
match st.poll(&mut self.0) {
Ok(state) => {
self.1 = state;
return Ok(Async::Ready(()));
}
Err(state) => {
self.1 = state;
return Ok(Async::NotReady)
}
}
}
}
}
}
}
@ -317,41 +247,40 @@ impl<S: 'static, H: PipelineHandler<S>> StartMiddlewares<S, H> {
}
}
fn poll(mut self, info: &mut PipelineInfo<S>) -> Result<PipelineState<S, H>, PipelineState<S, H>>
fn poll(&mut self, info: &mut PipelineInfo<S>) -> Option<PipelineState<S, H>>
{
let len = info.mws.len();
'outer: loop {
match self.fut.as_mut().unwrap().poll() {
Ok(Async::NotReady) =>
return Err(PipelineState::Starting(self)),
Ok(Async::NotReady) => return None,
Ok(Async::Ready(resp)) => {
info.count += 1;
if let Some(resp) = resp {
return Ok(RunMiddlewares::init(info, resp));
return Some(RunMiddlewares::init(info, resp));
}
if info.count == len {
let reply = (*self.hnd.borrow_mut()).handle(info.req.clone());
return Ok(WaitingResponse::init(info, reply));
return Some(WaitingResponse::init(info, reply));
} else {
loop {
match info.mws[info.count].start(info.req_mut()) {
Ok(Started::Done) =>
info.count += 1,
Ok(Started::Response(resp)) => {
return Ok(RunMiddlewares::init(info, resp));
return Some(RunMiddlewares::init(info, resp));
},
Ok(Started::Future(fut)) => {
self.fut = Some(fut);
continue 'outer
},
Err(err) =>
return Ok(ProcessResponse::init(err.into()))
return Some(ProcessResponse::init(err.into()))
}
}
}
}
Err(err) =>
return Ok(ProcessResponse::init(err.into()))
return Some(ProcessResponse::init(err.into()))
}
}
}
@ -378,15 +307,14 @@ impl<S: 'static, H> WaitingResponse<S, H> {
}
}
fn poll(mut self, info: &mut PipelineInfo<S>) -> Result<PipelineState<S, H>, PipelineState<S, H>>
fn poll(&mut self, info: &mut PipelineInfo<S>) -> Option<PipelineState<S, H>>
{
match self.fut.poll() {
Ok(Async::NotReady) =>
Err(PipelineState::Handler(self)),
Ok(Async::NotReady) => None,
Ok(Async::Ready(response)) =>
Ok(RunMiddlewares::init(info, response)),
Some(RunMiddlewares::init(info, response)),
Err(err) =>
Ok(ProcessResponse::init(err.into())),
Some(ProcessResponse::init(err.into())),
}
}
}
@ -432,31 +360,30 @@ impl<S: 'static, H> RunMiddlewares<S, H> {
}
}
fn poll(mut self, info: &mut PipelineInfo<S>) -> Result<PipelineState<S,H>, PipelineState<S, H>>
{
fn poll(&mut self, info: &mut PipelineInfo<S>) -> Option<PipelineState<S, H>> {
let len = info.mws.len();
loop {
// poll latest fut
let mut resp = match self.fut.as_mut().unwrap().poll() {
Ok(Async::NotReady) => {
return Err(PipelineState::RunMiddlewares(self))
return None
}
Ok(Async::Ready(resp)) => {
self.curr += 1;
resp
}
Err(err) =>
return Ok(ProcessResponse::init(err.into())),
return Some(ProcessResponse::init(err.into())),
};
loop {
if self.curr == len {
return Ok(ProcessResponse::init(resp));
return Some(ProcessResponse::init(resp));
} else {
match info.mws[self.curr].response(info.req_mut(), resp) {
Err(err) =>
return Ok(ProcessResponse::init(err.into())),
return Some(ProcessResponse::init(err.into())),
Ok(Response::Done(r)) => {
self.curr += 1;
resp = r
@ -601,8 +528,8 @@ impl<S: 'static, H> ProcessResponse<S, H> {
match io.write(chunk.as_ref()) {
Err(err) => {
info.error = Some(err.into());
return Ok(FinishingMiddlewares::init(
info, self.resp))
return Ok(
FinishingMiddlewares::init(info, self.resp))
},
Ok(result) => result
}
@ -656,8 +583,7 @@ impl<S: 'static, H> ProcessResponse<S, H> {
// restart io processing
return self.poll_io(io, info);
},
Ok(Async::NotReady) =>
return Err(PipelineState::Response(self)),
Ok(Async::NotReady) => return Err(PipelineState::Response(self)),
Err(err) => {
debug!("Error sending data: {}", err);
info.error = Some(err.into());
@ -680,7 +606,7 @@ impl<S: 'static, H> ProcessResponse<S, H> {
self.resp.set_response_size(io.written());
Ok(FinishingMiddlewares::init(info, self.resp))
}
_ => Err(PipelineState::Response(self))
_ => Err(PipelineState::Response(self)),
}
}
}
@ -699,15 +625,17 @@ impl<S: 'static, H> FinishingMiddlewares<S, H> {
if info.count == 0 {
Completed::init(info)
} else {
match (FinishingMiddlewares{resp: resp, fut: None,
_s: PhantomData, _h: PhantomData}).poll(info) {
Ok(st) | Err(st) => st,
let mut state = FinishingMiddlewares{resp: resp, fut: None,
_s: PhantomData, _h: PhantomData};
if let Some(st) = state.poll(info) {
st
} else {
PipelineState::Finishing(state)
}
}
}
fn poll(mut self, info: &mut PipelineInfo<S>) -> Result<PipelineState<S, H>, PipelineState<S, H>>
{
fn poll(&mut self, info: &mut PipelineInfo<S>) -> Option<PipelineState<S, H>> {
loop {
// poll latest fut
let not_ready = if let Some(ref mut fut) = self.fut {
@ -727,7 +655,7 @@ impl<S: 'static, H> FinishingMiddlewares<S, H> {
false
};
if not_ready {
return Ok(PipelineState::Finishing(self))
return None;
}
self.fut = None;
info.count -= 1;
@ -735,7 +663,7 @@ impl<S: 'static, H> FinishingMiddlewares<S, H> {
match info.mws[info.count].finish(info.req_mut(), &self.resp) {
Finished::Done => {
if info.count == 0 {
return Ok(Completed::init(info))
return Some(Completed::init(info))
}
}
Finished::Future(fut) => {
@ -760,13 +688,11 @@ impl<S, H> Completed<S, H> {
}
#[inline]
fn poll(self, info: &mut PipelineInfo<S>) -> Result<PipelineState<S, H>, PipelineState<S, H>> {
fn poll(&mut self, info: &mut PipelineInfo<S>) -> Option<PipelineState<S, H>> {
match info.poll_context() {
Ok(Async::NotReady) =>
Ok(PipelineState::Completed(Completed(PhantomData, PhantomData))),
Ok(Async::Ready(())) =>
Ok(PipelineState::None),
Err(_) => Ok(PipelineState::Error),
Ok(Async::NotReady) => None,
Ok(Async::Ready(())) => Some(PipelineState::None),
Err(_) => Some(PipelineState::Error),
}
}
}
@ -806,17 +732,17 @@ mod tests {
info.context = Some(Box::new(ctx));
let mut state = Completed::<(), Inner<()>>::init(&mut info).completed().unwrap();
let st = state.poll(&mut info).ok().unwrap();
let pp = Pipeline(info, st);
assert!(state.poll(&mut info).is_none());
let pp = Pipeline(info, PipelineState::Completed(state));
assert!(!pp.is_done());
let Pipeline(mut info, st) = pp;
state = st.completed().unwrap();
let mut st = st.completed().unwrap();
drop(addr);
state.poll(&mut info).ok().unwrap().is_none().unwrap();
assert!(st.poll(&mut info).unwrap().is_none().unwrap());
result(Ok::<_, ()>(()))
})).unwrap()
})).unwrap();
}
}