use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::action::{AcknowledgementDisposition, PrintAction};
use crate::adjustable::Adjustable;
use crate::assessment::AgentAssessment;
use crate::ids::{ActionId, EventId, InterventionId, PrintId};
use crate::image::ImageRef;
use crate::intervention::InterventionOutcome;
use crate::policy::PolicyDecision;
use crate::raw::RawBytes;
use crate::timestamp::Timestamp;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub enum EventSource {
Obico,
Operator,
Agent,
System,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub enum ObicoNotificationType {
Started,
Done,
Cancelled,
Paused,
Resumed,
FilamentChange,
HeaterCooled,
HeaterTarget,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ObicoFailureAlertPayload {
pub is_warning: bool,
pub print_paused: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub obico_print_id: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file_name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub started_at: Option<Timestamp>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ended_at: Option<Timestamp>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ObicoPrinterNotificationPayload {
pub notification_type: ObicoNotificationType,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub obico_print_id: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file_name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub started_at: Option<Timestamp>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ended_at: Option<Timestamp>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct MalformedExternalEventPayload {
pub detail: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub enum PortFailureSite {
PrinterSnapshot,
PrinterJob,
ImageWrite,
SupervisionTurn,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct PortFailurePayload {
pub event_id: EventId,
pub site: PortFailureSite,
pub detail: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ActionRequestedPayload {
pub action_id: ActionId,
pub action: PrintAction,
pub actor: crate::action::Actor,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ActionExecutedPayload {
pub action_id: ActionId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub intervention_id: Option<InterventionId>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ActionRejectedPayload {
pub action_id: ActionId,
pub decision: PolicyDecision,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct InterventionExpiredPayload {
pub intervention_id: InterventionId,
pub adjustable: Adjustable,
pub outcome: InterventionOutcome,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct SupervisionSessionOpenedPayload {
pub session_name: String,
pub harness_identity: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct SupervisionSessionClosedPayload {
pub session_name: String,
pub close_reason: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct AgentAssessmentPayload {
pub session_name: String,
pub assessment: AgentAssessment,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct OperatorAcknowledgementPayload {
pub acknowledged_event_id: EventId,
pub disposition: AcknowledgementDisposition,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub enum StartupOutcome {
PrintAdopted,
SessionResumed {
session_name: String,
},
InterventionExpired {
intervention_id: InterventionId,
adjustable: Adjustable,
outcome: InterventionOutcome,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct StartupReconciliationPayload {
pub print_id: PrintId,
pub outcome: StartupOutcome,
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema,
)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub enum EventKind {
ObicoFailureAlert,
ObicoPrinterNotification,
MalformedExternalEvent,
ActionRequested,
ActionExecuted,
ActionRejected,
InterventionExpired,
SupervisionSessionOpened,
SupervisionSessionClosed,
AgentAssessment,
OperatorAcknowledgement,
PortFailure,
StartupReconciliation,
}
impl EventKind {
pub const ALL: [Self; 13] = [
Self::ObicoFailureAlert,
Self::ObicoPrinterNotification,
Self::MalformedExternalEvent,
Self::ActionRequested,
Self::ActionExecuted,
Self::ActionRejected,
Self::InterventionExpired,
Self::SupervisionSessionOpened,
Self::SupervisionSessionClosed,
Self::AgentAssessment,
Self::OperatorAcknowledgement,
Self::PortFailure,
Self::StartupReconciliation,
];
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", content = "payload", rename_all = "snake_case")]
pub enum EventPayload {
ObicoFailureAlert(ObicoFailureAlertPayload),
ObicoPrinterNotification(ObicoPrinterNotificationPayload),
MalformedExternalEvent(MalformedExternalEventPayload),
ActionRequested(ActionRequestedPayload),
ActionExecuted(ActionExecutedPayload),
ActionRejected(ActionRejectedPayload),
InterventionExpired(InterventionExpiredPayload),
SupervisionSessionOpened(SupervisionSessionOpenedPayload),
SupervisionSessionClosed(SupervisionSessionClosedPayload),
AgentAssessment(AgentAssessmentPayload),
OperatorAcknowledgement(OperatorAcknowledgementPayload),
PortFailure(PortFailurePayload),
StartupReconciliation(StartupReconciliationPayload),
}
impl EventPayload {
#[must_use]
pub const fn kind(&self) -> EventKind {
match self {
Self::ObicoFailureAlert(_) => EventKind::ObicoFailureAlert,
Self::ObicoPrinterNotification(_) => EventKind::ObicoPrinterNotification,
Self::MalformedExternalEvent(_) => EventKind::MalformedExternalEvent,
Self::ActionRequested(_) => EventKind::ActionRequested,
Self::ActionExecuted(_) => EventKind::ActionExecuted,
Self::ActionRejected(_) => EventKind::ActionRejected,
Self::InterventionExpired(_) => EventKind::InterventionExpired,
Self::SupervisionSessionOpened(_) => EventKind::SupervisionSessionOpened,
Self::SupervisionSessionClosed(_) => EventKind::SupervisionSessionClosed,
Self::AgentAssessment(_) => EventKind::AgentAssessment,
Self::OperatorAcknowledgement(_) => EventKind::OperatorAcknowledgement,
Self::PortFailure(_) => EventKind::PortFailure,
Self::StartupReconciliation(_) => EventKind::StartupReconciliation,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct EventRecord {
pub id: EventId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub print_id: Option<PrintId>,
pub source: EventSource,
pub received_at: Timestamp,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub image: Option<ImageRef>,
#[serde(flatten)]
pub payload: EventPayload,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub raw: Option<RawBytes>,
}
impl EventRecord {
#[must_use]
pub const fn kind(&self) -> EventKind {
self.payload.kind()
}
}