use std::io::Write;
use syncbat::{SessionDelivery, SessionError, SubscriptionRuntimeError};
use super::super::error::NetbatError;
use super::super::limits::Limits;
use super::super::stream_frame::SubscriptionToken;
use super::{write_delivery, CURSOR_INVALID_CODE, CURSOR_MISMATCH_CODE};
pub(super) const UNKNOWN_SUBSCRIPTION_CODE: &str = "unknown_subscription";
pub(super) const MALFORMED_STREAM_FRAME_CODE: &str = "malformed_stream_frame";
pub(super) const INTERNAL_ERROR_CODE: &str = "internal_error";
pub(super) fn runtime_failure_code(error: &SubscriptionRuntimeError) -> &'static str {
match error {
SubscriptionRuntimeError::Store(_)
| SubscriptionRuntimeError::EnvelopeEncoding(_)
| SubscriptionRuntimeError::Worker(_) => INTERNAL_ERROR_CODE,
SubscriptionRuntimeError::CursorInvalid { .. } => CURSOR_INVALID_CODE,
SubscriptionRuntimeError::CursorMismatch { .. } => CURSOR_MISMATCH_CODE,
SubscriptionRuntimeError::UnknownSubscription { .. } => UNKNOWN_SUBSCRIPTION_CODE,
SubscriptionRuntimeError::InvalidSubscriptionId { .. }
| SubscriptionRuntimeError::DuplicateSubscription { .. }
| SubscriptionRuntimeError::InvalidRoute { .. }
| SubscriptionRuntimeError::InvalidConfig { .. }
| SubscriptionRuntimeError::AckInvalid { .. } => MALFORMED_STREAM_FRAME_CODE,
}
}
pub(super) fn write_runtime_failure(
writer: &mut impl Write,
subscription_id: &SubscriptionToken,
error: &SubscriptionRuntimeError,
limits: &Limits,
) -> Result<(), NetbatError> {
let delivery = SessionDelivery::Error(SessionError {
subscription_id: Some(subscription_id.as_str().to_owned()),
code: runtime_failure_code(error),
last_delivered_cursor: None,
last_acked_cursor: None,
message: b"subscription runtime poll failed".to_vec(),
});
write_delivery(writer, &delivery, limits)
}
pub(super) fn map_runtime_error(error: &SubscriptionRuntimeError) -> NetbatError {
NetbatError::MalformedStreamFrame {
reason: match error {
SubscriptionRuntimeError::Store(_) => "store error during stream poll",
SubscriptionRuntimeError::InvalidSubscriptionId { reason } => reason,
SubscriptionRuntimeError::DuplicateSubscription { .. } => {
"duplicate subscription route"
}
SubscriptionRuntimeError::InvalidRoute { reason }
| SubscriptionRuntimeError::InvalidConfig { reason } => reason,
SubscriptionRuntimeError::UnknownSubscription { .. } => "unknown subscription",
SubscriptionRuntimeError::CursorInvalid { reason } => reason,
SubscriptionRuntimeError::CursorMismatch { reason } => reason,
SubscriptionRuntimeError::EnvelopeEncoding(_) => "envelope encoding failed",
SubscriptionRuntimeError::Worker(_) => "subscription worker failed",
SubscriptionRuntimeError::AckInvalid { reason } => reason,
},
}
}