Skip to content

Commit

Permalink
Version 0.10.5 -- Error types are now a sized enum, instead of boxed …
Browse files Browse the repository at this point in the history
…errors.
  • Loading branch information
wireboy5 committed Nov 5, 2024
1 parent 60e0a8f commit f71e425
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 11 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Changelog

## 0.10.5 -- 2024-11-5

Version 0.10.5 changes `MessageSender`s to return a sized error type.
This type was intentionally made to *not* be irrefutable, as this could cause breaking changes across features.

## 0.10.4 -- 2024-11-5

Version 0.10.4 changes [`MessageSenders`] to also return boxed errors, enabling delegates to fail to send messages.
Version 0.10.4 changes `MessageSenders` to also return boxed errors, enabling delegates to fail to send messages.
Previously messages had been infallible, however this provided no way for networked delegates to fail.

## 0.10.3 -- 2024-11-3
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion fluxion/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ homepage = "https://fluxion.peperworx.com/"
categories = ["concurrency"]
keywords = ["actor", "distributed", "async", "fluxion"]
readme = "./README.md"
version = "0.10.4"
version = "0.10.5"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
4 changes: 2 additions & 2 deletions fluxion/examples/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use std::{collections::HashMap, marker::PhantomData, sync::Arc};


use fluxion::{actor, message, Delegate, Handler, Identifier, LocalRef, Message, MessageID, MessageSender};
use fluxion::{actor, message, Delegate, Handler, Identifier, LocalRef, Message, MessageID, MessageSendError, MessageSender};
use maitake_sync::RwLock;
use serde::{Deserialize, Serialize};
use slacktor::{ActorHandle, Slacktor};
Expand Down Expand Up @@ -61,7 +61,7 @@ struct DelegateSender<M: Message + MessageID> {
impl<M: Message + MessageID + Serialize> fluxion::MessageSender<M> for DelegateSender<M>
where M::Result: for<'de> Deserialize<'de> {

async fn send(&self,message:M) -> Result<M::Result, Box<dyn std::error::Error>> {
async fn send(&self,message:M) -> Result<M::Result, MessageSendError> {
// Send the message
let res = self.other_delegate.send(DelegateMessage(self.actor_id, M::ID.to_string(), bincode::serialize(&message).unwrap())).await;

Expand Down
64 changes: 62 additions & 2 deletions fluxion/src/message.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,80 @@

use core::error::Error;

use slacktor::Message;

#[cfg(feature="serde")]
use crate::MessageID;

/// # [`MessageSendError`]
/// An error type that might be returned during a message send.
#[derive(Debug)]
#[non_exhaustive]
pub enum MessageSendError {
#[cfg(feature = "serde")]
SerializationError {
message: alloc::string::String,
source: alloc::boxed::Box<dyn core::error::Error>,
},
#[cfg(feature = "serde")]
DeserializationError {
message: alloc::string::String,
source: alloc::boxed::Box<dyn core::error::Error>,
},
#[cfg(feature = "foreign")]
DelegateError {
message: alloc::string::String,
source: alloc::boxed::Box<dyn core::error::Error>,
},
UnknownError(alloc::boxed::Box<dyn Error>),
}

impl core::fmt::Display for MessageSendError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let message = match self {
#[cfg(feature = "serde")]
MessageSendError::SerializationError { message, source: _ } => message.clone(),
#[cfg(feature = "serde")]
MessageSendError::DeserializationError { message, source: _ } => message.clone(),
#[cfg(feature = "foreign")]
MessageSendError::DelegateError { message, source: _ } => message.clone(),
MessageSendError::UnknownError(e) => alloc::format!("{e}"),
};

write!(f, "MessageSendError: {message}")
}
}

impl core::error::Error for MessageSendError {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self {
#[cfg(feature = "serde")]
Self::SerializationError { message: _, source } => Some(source.as_ref()),
#[cfg(feature = "serde")]
Self::DeserializationError { message: _, source } => Some(source.as_ref()),
#[cfg(feature = "foreign")]
Self::DelegateError { message: _, source } => Some(source.as_ref()),
Self::UnknownError(e) => Some(e.as_ref()),
}
}

fn description(&self) -> &str {
"description() is deprecated; use Display"
}
}

/// # [`IndeterminateMessage`]
/// An indeterminate message is a message for which it has not yet been determined whether it will be serialized.
/// Because of this, indeterminate messages require serde traits to be implemented, which is not the case with local messages.
#[cfg(feature = "serde")]
pub trait IndeterminateMessage: Message + MessageID + serde::Serialize + for<'a> serde::Deserialize<'a>
where Self: Message + serde::Serialize + for<'a> serde::Deserialize<'a>,
Self::Result: serde::Serialize + for<'a> serde::Deserialize<'a>{}
Self::Result: serde::Serialize + for<'a> serde::Deserialize<'a>{}

#[cfg(feature = "serde")]
impl<T> IndeterminateMessage for T
where T: Message + MessageID + serde::Serialize + for<'a> serde::Deserialize<'a>,
Self::Result: serde::Serialize + for<'a> serde::Deserialize<'a> {}
Self::Result: serde::Serialize + for<'a> serde::Deserialize<'a> {}


/// # [`IndeterminateMessage`]
Expand Down
7 changes: 3 additions & 4 deletions fluxion/src/references.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@


use core::error::Error;

use crate::{Actor, ActorWrapper, Delegate, Handler, Message};
use crate::{Actor, ActorWrapper, Delegate, Handler, Message, MessageSendError};
use alloc::boxed::Box;

/// # [`ActorRef`]
Expand All @@ -28,7 +27,7 @@ pub trait MessageSender<M: Message>: Send + Sync + 'static {
/// For [`LocalRef`], the message send will never fail, however delegates may return an error upon sending.
/// These errors are generally not recoverable, and should be interpreted as meaning that the
/// target actor no longer exists/is no longer accessible.
async fn send(&self, message: M) -> Result<M::Result, Box<dyn Error>>;
async fn send(&self, message: M) -> Result<M::Result, MessageSendError>;
}


Expand All @@ -53,7 +52,7 @@ impl<A: Actor, D: Delegate> Clone for LocalRef<A, D> {
impl<A: Handler<M>, M: Message, D: Delegate> MessageSender<M> for LocalRef<A, D> {

#[inline]
async fn send(&self, message: M) -> Result<M::Result, Box<dyn Error>> {
async fn send(&self, message: M) -> Result<M::Result, MessageSendError> {
Ok(self.0.send(message).await)
}
}

0 comments on commit f71e425

Please sign in to comment.