use std::{
panic::{
AssertUnwindSafe,
catch_unwind,
},
sync::Arc,
};
use crate::{
TaskStatus,
service::SubmissionError,
};
use super::TaskId;
pub trait TaskHook: Send + Sync + 'static {
#[inline]
fn on_accepted(&self, _task_id: TaskId) {}
#[inline]
fn on_rejected(&self, _error: &SubmissionError) {}
#[inline]
fn on_started(&self, _task_id: TaskId) {}
#[inline]
fn on_finished(&self, _task_id: TaskId, _status: TaskStatus) {}
}
fn contain_hook_panic(callback: impl FnOnce()) {
if catch_unwind(AssertUnwindSafe(callback)).is_err() {
log::warn!("task hook panicked");
}
}
#[inline]
pub(crate) fn notify_accepted(hook: &dyn TaskHook, task_id: TaskId) {
contain_hook_panic(|| hook.on_accepted(task_id));
}
#[inline]
pub(crate) fn notify_rejected(hook: &dyn TaskHook, error: &SubmissionError) {
contain_hook_panic(|| hook.on_rejected(error));
}
#[inline]
pub(crate) fn notify_rejected_optional(hook: Option<&Arc<dyn TaskHook>>, error: &SubmissionError) {
if let Some(hook) = hook {
notify_rejected(hook.as_ref(), error);
}
}
#[inline]
pub(crate) fn notify_started(hook: &dyn TaskHook, task_id: TaskId) {
contain_hook_panic(|| hook.on_started(task_id));
}
#[inline]
pub(crate) fn notify_finished(hook: &dyn TaskHook, task_id: TaskId, status: TaskStatus) {
contain_hook_panic(|| hook.on_finished(task_id, status));
}