MCPcopy Create free account
hub / github.com/Botloader/botloader / discord_request_retry

Function discord_request_retry

components/runtime/src/extensions/discord.rs:205–271  ·  view source on GitHub ↗
(
    state: &Rc<RefCell<OpState>>,
    f: impl Fn(Arc<DiscordConfig>) -> Fut,
)

Source from the content-addressed store, hash-verified

203}
204
205pub async fn discord_request_retry<T: Send, Fut>(
206 state: &Rc<RefCell<OpState>>,
207 f: impl Fn(Arc<DiscordConfig>) -> Fut,
208) -> Result<T, AnyError>
209where
210 Fut: Future<Output = Result<T, AnyError>>,
211{
212 let rt_handle = {
213 let state = state.borrow();
214 let rt_ctx: &RuntimeContext = state.borrow();
215 rt_ctx.main_tokio_runtime.clone()
216 };
217
218 let mut retry_sleep = Duration::from_secs(1);
219 let max_sleep = Duration::from_secs(60);
220 let mut retry_count = 1;
221
222 let res = loop {
223 let discord_config = {
224 let state = state.borrow();
225 let rt_ctx: &RuntimeContext = state.borrow();
226 rt_ctx.discord_config.clone()
227 };
228
229 // We run the request on the main botloader tokio runtime, the vm runtime is disposed of on shutdown
230 // and any futures cancelled, which twilights ratelimit handling does not like
231 let inner_fut = f(discord_config);
232 let fut = WrappedFuture {
233 inner: inner_fut,
234 rt: rt_handle.clone(),
235 };
236
237 let retry_reason = match fut.await {
238 Ok(v) => break Ok(v),
239 Err(err) => match err.downcast::<twilight_http::Error>() {
240 Ok(discord_err) => match discord_err.kind() {
241 ErrorType::RequestCanceled => "REQUEST_CANCELED",
242 ErrorType::RequestError => "REQUEST_ERROR",
243
244 // I've disabled this for now, from experience this could lead to requests being processed twice.
245 // ErrorType::RequestTimedOut => "REQUEST_TIMEOUT",
246 ErrorType::Response { status, .. } if status.get() == 429 => {
247 if check_bad_request(state, status.get()).is_err() {
248 break Err(anyhow::anyhow!(
249 "Hit maximum number of bad requests within a time period"
250 ));
251 }
252
253 "RATELIMIT_429"
254 }
255 _ => break Err(handle_discord_error(state, discord_err)),
256 },
257 Err(err) => break Err(err),
258 },
259 };
260 tokio::time::sleep(retry_sleep).await;
261 retry_sleep = retry_sleep * 2;
262 if retry_sleep > max_sleep {

Callers 2

Calls 4

check_bad_requestFunction · 0.85
handle_discord_errorFunction · 0.85
kindMethod · 0.80
getMethod · 0.45

Tested by

no test coverage detected