fix cancellation logic for server fn requests

This commit is contained in:
Greg Johnston 2024-04-13 17:18:05 -04:00
parent 60d883a26c
commit e4f3cf9cca
2 changed files with 25 additions and 51 deletions

View file

@ -39,18 +39,11 @@ pub mod browser {
use super::Client;
use crate::{
error::ServerFnError,
request::browser::{AbortOnDrop, BrowserRequest, RequestInner},
request::browser::{BrowserRequest, RequestInner},
response::browser::BrowserResponse,
};
use gloo_net::{http::Response, Error};
use send_wrapper::SendWrapper;
use std::{
future::Future,
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
};
use web_sys::AbortController;
use std::future::Future;
/// Implements [`Client`] for a `fetch` request in the browser.
pub struct BrowserClient;
@ -64,54 +57,26 @@ pub mod browser {
) -> impl Future<Output = Result<Self::Response, ServerFnError<CustErr>>>
+ Send {
SendWrapper::new(async move {
let mut req = req.0.take();
let req = req.0.take();
let RequestInner {
request,
abort_ctrl,
mut abort_ctrl,
} = req;
/*BrowserRequestFuture {
request_fut: request.send(),
abort_ctrl,
cust_err: PhantomData,
}*/
request
let res = request
.send()
.await
.map(|res| BrowserResponse(SendWrapper::new(res)))
.map_err(|e| ServerFnError::Request(e.to_string()))
.map_err(|e| ServerFnError::Request(e.to_string()));
// at this point, the future has successfully resolved without being dropped, so we
// can prevent the `AbortController` from firing
if let Some(ctrl) = abort_ctrl.as_mut() {
ctrl.prevent_cancellation();
}
res
})
}
}
/*pin_project_lite::pin_project! {
struct BrowserRequestFuture<Fut, CustErr>
where
Fut: Future<Output = Result<Response, Error>>,
{
#[pin]
request_fut: Fut,
abort_ctrl: Option<AbortOnDrop>,
cust_err: PhantomData<CustErr>
}
}
impl<Fut, CustErr> Future for BrowserRequestFuture<Fut, CustErr>
where
Fut: Future<Output = Result<Response, Error>>,
{
type Output = Result<BrowserResponse, ServerFnError<CustErr>>;
fn poll(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Self::Output> {
let this = self.project();
match this.request_fut.poll(cx) {
Poll::Ready(value) => todo!(),
Poll::Pending => Poll::Pending,
}
}
}*/
}
#[cfg(feature = "reqwest")]

View file

@ -25,11 +25,20 @@ pub(crate) struct RequestInner {
}
#[derive(Debug)]
pub(crate) struct AbortOnDrop(AbortController);
pub(crate) struct AbortOnDrop(Option<AbortController>);
impl AbortOnDrop {
/// Prevents the request from being aborted on drop.
pub fn prevent_cancellation(&mut self) {
self.0.take();
}
}
impl Drop for AbortOnDrop {
fn drop(&mut self) {
self.0.abort();
if let Some(inner) = self.0.take() {
inner.abort();
}
}
}
@ -72,7 +81,7 @@ impl From<FormData> for BrowserFormData {
fn abort_signal() -> (Option<AbortOnDrop>, Option<AbortSignal>) {
let ctrl = AbortController::new().ok();
let signal = ctrl.as_ref().map(|ctrl| ctrl.signal());
(ctrl.map(AbortOnDrop), signal)
(ctrl.map(|ctrl| AbortOnDrop(Some(ctrl))), signal)
}
impl<CustErr> ClientReq<CustErr> for BrowserRequest {