Rebrand to Galaxy, major improvements to Bedrock support, still needs some TLC though

This commit is contained in:
Ryan Ward
2026-05-07 11:29:34 -05:00
parent f4e2475c60
commit a41cbd8cc7
2433 changed files with 14208 additions and 9409 deletions
+31
View File
@@ -0,0 +1,31 @@
use super::registration::AnyErrorRegistration;
/// A version of [`ErrorExt`] that works for [`anyhow::Error`] (which does not
/// implement [`std::error::Error`]).
pub trait AnyhowErrorExt {
/// Returns whether or not an error is something that is actionable by our
/// engineering team.
fn is_actionable(&self) -> bool;
/// Reports the error.
fn report_error(&self);
}
impl AnyhowErrorExt for anyhow::Error {
fn is_actionable(&self) -> bool {
for cause in self.chain() {
for imp in inventory::iter::<&'static dyn AnyErrorRegistration>() {
if imp.downcast_and_is_actionable(cause) == Some(false) {
return false;
}
}
}
true
}
fn report_error(&self) {
#[cfg(feature = "crash_reporting")]
sentry::integrations::anyhow::capture_anyhow(self);
}
}
@@ -0,0 +1,60 @@
use std::marker::PhantomData;
use super::ErrorExt;
#[macro_export]
macro_rules! register_error {
($error:ty) => {
impl $crate::errors::RegisteredError for $error {}
$crate::errors::submit! {
$crate::errors::ErrorRegistration::<$error>::adapt()
}
};
}
pub use register_error;
/// Marker trait for known error events. We rely on this to implement [`ErrorExt`] for [`anyhow::Error`]
/// in a way that delegates to errors in the context chain.
///
/// DO NOT implement this trait directly - use the [`register_error!`] macro instead.
pub trait RegisteredError {}
/// A type-erased version of [`ErrorRegistration`]. This is only used by the
/// [`register_error!`] macro implementation.
#[doc(hidden)]
pub trait AnyErrorRegistration: Sync {
// Returns true if
fn downcast_and_is_actionable(&self, error: &(dyn std::error::Error + 'static))
-> Option<bool>;
}
/// Adapter for statically registering all [`ErrorExt`] implementations.
#[doc(hidden)]
pub struct ErrorRegistration<T: ErrorExt + 'static> {
/// Marker that `ErrorRegistration` references `T`, but doesn't own a `T` value.
/// See https://doc.rust-lang.org/nomicon/phantom-data.html
_marker: PhantomData<fn(T) -> T>,
}
impl<T: ErrorExt + 'static> ErrorRegistration<T> {
pub const fn adapt() -> &'static dyn AnyErrorRegistration {
&Self {
_marker: PhantomData,
}
}
}
impl<T: ErrorExt + 'static> AnyErrorRegistration for ErrorRegistration<T> {
fn downcast_and_is_actionable(
&self,
error: &(dyn std::error::Error + 'static),
) -> Option<bool> {
let err = error.downcast_ref::<T>()?;
Some(err.is_actionable())
}
}
// Collect adapters for all registered error types. Because `inventory::collect!` requires a
// concrete type, we use `&static dyn Trait` to erase the generics.
inventory::collect!(&'static dyn AnyErrorRegistration);
+48
View File
@@ -0,0 +1,48 @@
use http::StatusCode;
use super::{register_error, ErrorExt};
impl ErrorExt for reqwest::Error {
fn is_actionable(&self) -> bool {
// Outside of timeouts, there's nothing we can do about errors
// that occur prior to the successful receipt of an HTTP
// response.
// There's no way to check for connection errors via web APIs, so
// `is_connect` can only be called on native platforms.
#[cfg(not(target_family = "wasm"))]
if self.is_connect() {
return false;
}
if self.is_request() || self.is_body() || self.is_decode() {
return false;
}
// If we're getting a capacity error from the server, then that should trip a server-side
// alert. A duplicate report in Sentry isn't helpful.
if self.status() == Some(StatusCode::TOO_MANY_REQUESTS) {
return false;
}
// Internal server errors (5xx) are server-side issues that we can't act upon from the client.
if self.status().is_some_and(|status| status.is_server_error()) {
return false;
}
// If we're making a request to the staging server and get back
// a 403 Forbidden, the user is probably not whitelisted to talk
// to staging from their current IP address, so downgrade to a
// warning.
if let (Some(url), Some(status)) = (self.url(), self.status()) {
if let Some(domain) = url.domain() {
if domain == "staging.warp.dev" && status == StatusCode::FORBIDDEN {
return false;
}
}
}
true
}
}
register_error!(reqwest::Error);
+19
View File
@@ -0,0 +1,19 @@
use super::{register_error, ErrorExt};
impl ErrorExt for tokio::task::JoinError {
fn is_actionable(&self) -> bool {
// If the task was cancelled (aborted), this is expected behavior and not actionable.
if self.is_cancelled() {
return false;
}
// If the task panicked, this is actionable - we need to know about panics.
if self.is_panic() {
return true;
}
// Other join errors are actionable.
true
}
}
register_error!(tokio::task::JoinError);
@@ -0,0 +1,25 @@
use http::StatusCode;
use super::{register_error, ErrorExt};
impl ErrorExt for websocket::tungstenite::Error {
fn is_actionable(&self) -> bool {
match self {
Self::Http(res) => {
// Capacity errors from the server aren't actionable client-side.
if res.status() == StatusCode::TOO_MANY_REQUESTS {
return false;
}
// Internal server errors (5xx) are server-side issues that we can't act upon from the client.
if res.status().is_server_error() {
return false;
}
true
}
_ => true,
}
}
}
register_error!(websocket::tungstenite::Error);