prost icon indicating copy to clipboard operation
prost copied to clipboard

Support for `std::sync::Arc` as indirection

Open segeljakt opened this issue 4 years ago • 9 comments

Hi, I wonder, would be possible to allow prost-types to be wrapped inside std::sync::Arc? The reason is that I want my messages to be sendable across both processes and threads. When sent across processes, my messages should be serialized/deserialized with prost. When sent across threads, I would like to use reference counting.

#[derive(prost::Message)]
struct MyMessage {
    #[prost(string, tag = "1")]
    label: Arc<String>,
    #[prost(message, tag = "2")]
    payload: Arc<Payload>,
}

#[derive(prost::Message)]
struct Payload {
    #[prost(i32, repeated, tag = "1")]
    stuff: Vec<i32>,
}

Thanks for the great crate.

segeljakt avatar Jan 19 '21 22:01 segeljakt

This would also be nice in conjunction with Tonic servers. If we had something analogous to bytes or btree_map, like:

Config::new()
    .arc(&[".my_service.FooRequest.my_big_field"])
    .compile_protos(...)

…then we could get away with fewer wasted clones in RPC handlers.

I think that this might be nice, but am not strongly lobbying for it, and wouldn’t be too upset if it were wontfixed.

wchargin avatar Mar 04 '21 19:03 wchargin

Sounds like a good addition! We should probably also support Box and Rc similarly.

danburkert avatar Mar 04 '21 19:03 danburkert

This could also be helpful (I think) for cases where a large object is received in the request and needs to outlive it. Allowing that object to be an Arc would allow it to be taken outside the request/response lifetime without copying.

bjchambers avatar May 21 '21 23:05 bjchambers

🤔Seems it's possible to implement the feature, I'll try this.

name1e5s avatar Apr 01 '22 15:04 name1e5s

will this be on the road map?

The-Mr-L avatar May 01 '22 13:05 The-Mr-L

Sounds like a good addition! We should probably also support Box and Rc similarly.

Rc cannot be supported since prost::Message requires Send + Sync

ldm0 avatar Oct 17 '22 19:10 ldm0

Yeah I can here just to comment/upvote this. I'm trying to use a watch with tonic and I need to clone the message that hits each receiver because arc isn't supported. I can probably modify some of the generated code.

jasongoodwin avatar Feb 03 '23 07:02 jasongoodwin

I can probably modify some of the generated code.

@jasongoodwin do you happen to have an implementation for this? I'm in a similar position, only the data I'm sending can get quite large.

AshleySchaeffer avatar Dec 16 '23 11:12 AshleySchaeffer

Rc cannot be supported since prost::Message requires Send + Sync

Honestly... why does Message require Send + Sync? I peeked at the associated functions and there didn't seem any reason for it.

It's actually blocking me for another reason: I tried implementing Message for Cow<str>. I can logically encode and decode a Cow<str> into proto string:

  1. Encoding is easy, it can borrow basically all of string encoding infrastructure.
  2. Decoding is not bad either:
    • If it's an empty string, then decode it as Cow::Borrowed("").
    • If it's not an empty string, then decode it as Cow::Owned String.

But due to the requirement of Message to be Send + Sync, it doesn't matter.

The requirement of Send is particularly odd, because I would think serializing to protobuf is one way you can send non-Send types to other threads...

morrisonlevi avatar Jan 31 '24 03:01 morrisonlevi