How to handle non-Clone data in Message?

Hi, I have a small problem with certain types when I want to put them in a Message. For example, my application uses sqlx for database connections. Because sqlx is async, the tasks can be submitted to the async runtime using an iced::Command. I want to handle possible sqlx errors in my application, so a Message could look like this: Message::QueryResponse(Result<MyData, sqlx::Error>). But this does not work, because Message is required to implement Clone + Debug and sqlx::Error does not implement Clone.

For non-Debug types it would be easy. I could simply wrap them in a Newtype and implement Debug myself and then destructure it in the match expression.

A workaround I’ve used is to wrap the Result in an Arc<Mutex<Option<Result<...>>>>. (The Option is there so I can get ownership of the value with Option::take() and not only a mutable reference). But this not the most ergonomic thing to use and is quite messy.

Is there a cleaner way to achieve this? I’ve seen the pokédex example, where the reqwest::Error is converted to a Clone-able type, but you lose all the information from reqwest.

1 Like

I don’t know whether this is the recommended approach, but I have personally dealt with the exact same problem by wrapping the non-cloneable error type with an std::sync::Arc.

So, for instance, in your situation, I would use Result<MyData, std::sync::Arc<sqlx::Error>>.

This approach will likely add some overhead, but it will let you preserve the original error.

I’m curious to hear what others have to say about this, however.

See my comment in this PR:

1 Like

Thanks for the link! Now I better understand how the elm architecture is supposed to work.

Before opening this thread, I tried GitHub’s search, but could not find anything :thinking: