pub use fastly_shared::CacheOverride;
use super::SendError;
use crate::http::response::{handles_to_response, FastlyResponseMetadata};
use crate::{Request, Response};
use std::collections::HashMap;
pub mod handle;
pub use handle::{select_handles, PendingRequestHandle, PollHandleResult};
pub struct PendingRequest {
handle: PendingRequestHandle,
pub(super) metadata: FastlyResponseMetadata,
}
impl PendingRequest {
pub(super) fn new(handle: PendingRequestHandle, metadata: FastlyResponseMetadata) -> Self {
Self { handle, metadata }
}
#[cfg_attr(
feature = "unstable-doc",
doc(include = "../../../docs/snippets/panics-responselimits.md")
)]
pub fn poll(self) -> PollResult {
let Self { handle, metadata } = self;
match handle.copy().poll() {
PollHandleResult::Pending(handle) => PollResult::Pending(Self { handle, metadata }),
PollHandleResult::Done(Ok((resp_handle, resp_body_handle))) => {
PollResult::Done(handles_to_response(resp_handle, resp_body_handle, metadata))
}
PollHandleResult::Done(Err(e)) => PollResult::Done(Err(SendError::from_pending_req(
Self { handle, metadata },
e,
))),
}
}
#[cfg_attr(
feature = "unstable-doc",
doc(include = "../../../docs/snippets/panics-responselimits.md")
)]
pub fn wait(self) -> Result<Response, SendError> {
let (resp_handle, resp_body_handle) =
try_with_pending_req!(self, self.handle.copy().wait());
handles_to_response(resp_handle, resp_body_handle, self.metadata)
}
pub fn sent_req(&self) -> &Request {
self.metadata
.sent_req()
.expect("sent_req must be present for a pending request")
}
}
pub enum PollResult {
Pending(PendingRequest),
Done(Result<Response, SendError>),
}
#[cfg_attr(
feature = "unstable-doc",
doc(include = "../../../docs/snippets/panics-responselimits.md")
)]
pub fn select<I>(pending_reqs: I) -> (Result<Response, SendError>, Vec<PendingRequest>)
where
I: IntoIterator<Item = PendingRequest>,
{
let (handles, mut handles_metadata) = {
let pending_reqs = pending_reqs.into_iter().collect::<Vec<_>>();
let mut handles = Vec::with_capacity(pending_reqs.len());
let mut handles_metadata = HashMap::with_capacity(pending_reqs.len());
for PendingRequest { handle, metadata } in pending_reqs {
handles_metadata.insert(handle.as_u32(), metadata);
handles.push(handle);
}
(handles, handles_metadata)
}; let (res, _, remaining_handles) = select_handles(handles);
let remaining = {
let mut remaining = Vec::with_capacity(remaining_handles.len());
for handle in remaining_handles {
let metadata = handles_metadata
.remove(&handle.as_u32())
.expect("handle exists in sent_req map");
remaining.push(PendingRequest { handle, metadata });
}
remaining
};
assert_eq!(handles_metadata.len(), 1); let (_, mut metadata) = handles_metadata.into_iter().next().unwrap();
let res = match res {
Ok((resp_handle, resp_body_handle)) => {
handles_to_response(resp_handle, resp_body_handle, metadata)
}
Err(e) => {
let sent_req = metadata
.take_sent_req()
.expect("sent_req must be present for a pending request");
Err(SendError::new(
metadata
.backend()
.expect("backend must be present for a pending request")
.name(),
sent_req,
e,
))
}
};
(res, remaining)
}