Skip to main content

BackendError

Derive Macro BackendError 

Source
#[derive(BackendError)]
{
    // Attributes available to this derive:
    #[backend_error]
}
Expand description

#[derive(BackendError)] — auto-implement a trait with the shape:

pub trait BackendError {
    fn is_retryable(&self) -> bool;
    fn is_auth_failure(&self) -> bool { false }
    fn kind(&self) -> &'static str;
}

The derive emits:

  • is_retryabletrue for variants tagged #[backend_error(transient)]
  • is_auth_failuretrue for variants tagged #[backend_error(auth)]
  • kind — delegates to self.discriminant() (requires #[derive(Discriminant)] to be on the same enum with method discriminant OR the consumer overrides via kind_method)

§Attributes

  • #[backend_error(trait_path = "::path::to::BackendError")] — fully-qualified trait path. Defaults to unqualified BackendError — consumer must use the_trait::BackendError in scope.
  • #[backend_error(kind_method = "kind")] — name of the &'static str-returning method to delegate kind() to (default "discriminant" — matches the default Discriminant method name).
  • Per-variant #[backend_error(transient)] — variant is transient (caller should retry).
  • Per-variant #[backend_error(auth)] — variant is an auth failure (HTTP 401/403 maps).
  • Per-variant #[backend_error(permanent)] — variant is permanent (caller must not retry). Default for unattributed variants.

§Round-trip with Discriminant

Pairs with Discriminant to deliver the BackendError contract in two derives:

use magma_converge::BackendError;  // trait in scope

#[derive(Debug, thiserror::Error, gen_platform::Discriminant, gen_platform::BackendError)]
#[discriminant(method = "discriminant", case = "snake")]
enum BlobStoreError {
    #[error("not found at {path:?}")]
    NotFound { path: String },

    #[error("permission denied at {path:?}")]
    #[backend_error(auth)]
    PermissionDenied { path: String },

    #[error("transient at {path:?}")]
    #[backend_error(transient)]
    Transient { path: String },

    #[error("permanent at {path:?}")]
    Permanent { path: String },
}

// Auto-generated:
//   impl BackendError for BlobStoreError {
//       fn is_retryable(&self) -> bool { matches!(self, Self::Transient { .. }) }
//       fn is_auth_failure(&self) -> bool { matches!(self, Self::PermissionDenied { .. }) }
//       fn kind(&self) -> &'static str { self.discriminant() }
//   }