mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-11 20:32:12 +00:00
store an error
This commit is contained in:
1 parent
e7bb263755
commit
691e5109a5
9 files changed
+47
-19
No files matched your search
@@ -63,6 +63,7 @@ mod tests {
|
||||
media_file_token: None,
|
||||
inference_job_token: None,
|
||||
third_party_id: None,
|
||||
maybe_error: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,6 +223,7 @@ mod tests {
|
||||
media_file_token: None,
|
||||
inference_job_token: None,
|
||||
third_party_id: None,
|
||||
maybe_error: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::notification::generate_deduplication_key::generate_deduplication_key;
|
||||
use crate::notification::notification_urgency::NotificationUrgency;
|
||||
|
||||
/// Details for a pager notification.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct NotificationDetails {
|
||||
/// Title or summary of the alert.
|
||||
pub title: String,
|
||||
@@ -42,6 +42,9 @@ pub struct NotificationDetails {
|
||||
|
||||
/// Third-party identifier associated with the event, if any.
|
||||
pub third_party_id: Option<String>,
|
||||
|
||||
/// The error that triggered this notification, if any.
|
||||
pub maybe_error: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
|
||||
}
|
||||
|
||||
impl NotificationDetails {
|
||||
@@ -50,6 +53,7 @@ impl NotificationDetails {
|
||||
}
|
||||
|
||||
/// Create a notification with a title and description.
|
||||
#[deprecated(note = "Use NotificationDetailsBuilder::from_title() instead")]
|
||||
pub fn with_title_and_description(title: String, description: String) -> Self {
|
||||
Self {
|
||||
title,
|
||||
@@ -64,10 +68,12 @@ impl NotificationDetails {
|
||||
media_file_token: None,
|
||||
inference_job_token: None,
|
||||
third_party_id: None,
|
||||
maybe_error: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a notification with just a title.
|
||||
#[deprecated(note = "Use NotificationDetailsBuilder::from_title() instead")]
|
||||
pub fn with_title(title: String) -> Self {
|
||||
Self {
|
||||
title,
|
||||
@@ -82,6 +88,7 @@ impl NotificationDetails {
|
||||
media_file_token: None,
|
||||
inference_job_token: None,
|
||||
third_party_id: None,
|
||||
maybe_error: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +99,11 @@ impl NotificationDetails {
|
||||
/// - The error's source chain (if any)
|
||||
/// - A backtrace (if available via `std::backtrace`)
|
||||
/// - The timestamp of the event
|
||||
pub fn from_error<E: Debug + Display>(error: &E) -> Self {
|
||||
///
|
||||
/// Note: this does not retain the error object itself. Use
|
||||
/// `NotificationDetailsBuilder::from_title().set_error()` to attach an error.
|
||||
#[deprecated(note = "Use NotificationDetailsBuilder::from_title().set_error() instead")]
|
||||
pub fn from_error_info<E: Debug + Display>(error: &E) -> Self {
|
||||
let title = format!("{}", error);
|
||||
|
||||
// Truncate the title to a reasonable length for alert titles.
|
||||
@@ -147,12 +158,15 @@ impl NotificationDetails {
|
||||
media_file_token: None,
|
||||
inference_job_token: None,
|
||||
third_party_id: None,
|
||||
maybe_error: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a notification from an error, with a custom title prefix.
|
||||
pub fn from_error_with_context<E: Debug + Display>(context: &str, error: &E) -> Self {
|
||||
let mut notification = Self::from_error(error);
|
||||
#[deprecated(note = "Use NotificationDetailsBuilder::from_title().set_error() instead")]
|
||||
pub fn from_error_info_with_context<E: Debug + Display>(context: &str, error: &E) -> Self {
|
||||
#[allow(deprecated)]
|
||||
let mut notification = Self::from_error_info(error);
|
||||
notification.title = format!("{}: {}", context, notification.title);
|
||||
if notification.title.len() > 200 {
|
||||
notification.title = format!("{}...", ¬ification.title[..197]);
|
||||
|
||||
@@ -17,6 +17,7 @@ pub struct NotificationDetailsBuilder {
|
||||
media_file_token: Option<String>,
|
||||
inference_job_token: Option<String>,
|
||||
third_party_id: Option<String>,
|
||||
maybe_error: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
|
||||
}
|
||||
|
||||
impl NotificationDetailsBuilder {
|
||||
@@ -35,16 +36,20 @@ impl NotificationDetailsBuilder {
|
||||
media_file_token: None,
|
||||
inference_job_token: None,
|
||||
third_party_id: None,
|
||||
maybe_error: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a builder from an error.
|
||||
/// Create a builder from an error's Display/Debug info.
|
||||
///
|
||||
/// Sets `is_from_error` to true and derives the summary and description
|
||||
/// from the error, matching the behavior of `NotificationDetails::from_error`.
|
||||
pub fn from_error<E: Debug + Display>(error: &E) -> Self {
|
||||
// TODO(bt,2026-03-30): Clean this up
|
||||
let details = NotificationDetails::from_error(error);
|
||||
/// Sets `is_from_error` to true and derives the title and description
|
||||
/// from the error. Does NOT retain the error object itself.
|
||||
///
|
||||
/// Use `from_title().set_error()` to attach the actual error.
|
||||
#[deprecated(note = "Use from_title().set_error() instead")]
|
||||
pub fn from_error_info<E: Debug + Display>(error: &E) -> Self {
|
||||
#[allow(deprecated)]
|
||||
let details = NotificationDetails::from_error_info(error);
|
||||
Self {
|
||||
title: details.title,
|
||||
description: details.description,
|
||||
@@ -58,9 +63,10 @@ impl NotificationDetailsBuilder {
|
||||
media_file_token: None,
|
||||
inference_job_token: None,
|
||||
third_party_id: None,
|
||||
maybe_error: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn set_title(mut self, title: String) -> Self {
|
||||
self.title = title;
|
||||
self
|
||||
@@ -111,6 +117,11 @@ impl NotificationDetailsBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_error(mut self, error: Option<Box<dyn std::error::Error + Send + Sync + 'static>>) -> Self {
|
||||
self.maybe_error = error;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> NotificationDetails {
|
||||
NotificationDetails {
|
||||
title: self.title,
|
||||
@@ -125,6 +136,7 @@ impl NotificationDetailsBuilder {
|
||||
media_file_token: self.media_file_token,
|
||||
inference_job_token: self.inference_job_token,
|
||||
third_party_id: self.third_party_id,
|
||||
maybe_error: self.maybe_error,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ pub fn alert_pager_and_return_err<T>(
|
||||
err: anyhow::Error,
|
||||
job: Option<&PendingSeedance2ProJob>,
|
||||
) -> anyhow::Result<T> {
|
||||
let mut builder = NotificationDetailsBuilder::from_error(&err)
|
||||
let mut builder = NotificationDetailsBuilder::from_error_info(&err)
|
||||
.set_title(title.to_string())
|
||||
.set_urgency(Some(NotificationUrgency::Medium));
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ pub async fn process_failed_job(
|
||||
err,
|
||||
);
|
||||
|
||||
let notification = NotificationDetailsBuilder::from_error(&err)
|
||||
let notification = NotificationDetailsBuilder::from_error_info(&err)
|
||||
.set_title("Seedance2Pro refund failed".to_string())
|
||||
.set_inference_job_token(Some(job.job_token.to_string()))
|
||||
.set_third_party_id(Some(job.order_id.to_string()))
|
||||
@@ -140,7 +140,7 @@ pub async fn process_failed_job(
|
||||
err
|
||||
);
|
||||
|
||||
let notification = NotificationDetailsBuilder::from_error(&err)
|
||||
let notification = NotificationDetailsBuilder::from_error_info(&err)
|
||||
.set_title("Seedance2Pro mark job failed error".to_string())
|
||||
.set_urgency(Some(NotificationUrgency::Medium))
|
||||
.build();
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn alert_pager_and_return_err<T>(
|
||||
title: &str,
|
||||
err: anyhow::Error,
|
||||
) -> anyhow::Result<T> {
|
||||
let notification = NotificationDetailsBuilder::from_error(&err)
|
||||
let notification = NotificationDetailsBuilder::from_error_info(&err)
|
||||
.set_title(title.to_string())
|
||||
.set_urgency(Some(NotificationUrgency::Medium))
|
||||
.build();
|
||||
|
||||
+2
-2
@@ -222,7 +222,7 @@ pub async fn seedance_2p0_multi_function_video_gen_handler(
|
||||
Err(err) => {
|
||||
warn!("Regular session fallback also failed for user {:?}: {:?}", user_token, err);
|
||||
if let Err(page_err) = server_state.pager.enqueue_page(
|
||||
NotificationDetailsBuilder::from_error(&err)
|
||||
NotificationDetailsBuilder::from_error_info(&err)
|
||||
.set_title("Seedance 2.0 generation failed (whitelist + fallback)".to_string())
|
||||
.set_urgency(Some(NotificationUrgency::High))
|
||||
.build()
|
||||
@@ -256,7 +256,7 @@ pub async fn seedance_2p0_multi_function_video_gen_handler(
|
||||
Err(err) => {
|
||||
warn!("Error calling seedance2pro generate_video: {:?}", err);
|
||||
if let Err(page_err) = server_state.pager.enqueue_page(
|
||||
NotificationDetailsBuilder::from_error(&err)
|
||||
NotificationDetailsBuilder::from_error_info(&err)
|
||||
.set_title("Seedance 2.0 generation failed".to_string())
|
||||
.set_urgency(Some(NotificationUrgency::High))
|
||||
.build()
|
||||
|
||||
+1
-1
@@ -120,7 +120,7 @@ pub async fn fal_webhook_handler(
|
||||
if let Err(ref err) = result {
|
||||
error!("FAL webhook error for request_id {}: {:?}", request_id, err);
|
||||
|
||||
let notification = NotificationDetailsBuilder::from_error(err)
|
||||
let notification = NotificationDetailsBuilder::from_error_info(err)
|
||||
.set_title("FAL webhook processing failed".to_string())
|
||||
.set_description(Some(format!(
|
||||
"FAL webhook failed for request_id: {}\n\nError: {:?}\n\nWebhook JSON Payload: {}",
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ pub async fn db_health_checker_thread(
|
||||
Ok(_) => {},
|
||||
}
|
||||
|
||||
let notification = NotificationDetailsBuilder::from_error(&database_error)
|
||||
let notification = NotificationDetailsBuilder::from_error_info(&database_error)
|
||||
.set_title("DB health check thread failed check".to_string())
|
||||
.set_urgency(Some(NotificationUrgency::High))
|
||||
.build();
|
||||
|
||||
Reference in new issue
Block a user