How to use pin and also change ownership

I am implementing an API for a network protocol. You can see my PR here, but I will try to distill the problem:

The protocol has an initial mode that allows ordinary requests/responses, which is handled using a ReplicationClient object. But one kind of request causes the protocol to enter a streaming mode, where lots of data is sent from server to client and only certain kinds of messages (e.g. stop, status update) can be sent from the client to the server.

I would like to use the rust type system properly to model this problem in a safe way, so that a caller can't accidentally send a normal request while in streaming mode.

The method that initiates streaming takes ownership of the original ReplicationClient object, and returns a ReplicationStream object. That prevents the caller from using the client object to issue ordinary requests while in streaming mode, which is prohibited by the protocol. See the physical_replication test and observe that the start_physical_replication method takes ownership of self.

The problem is, how do I stop streaming and go back to normal mode? My first idea was to have a stop_replication method on the ReplicationStream object, which takes ownership of self, issues a stop message and then returns the original ReplicationClient object. But this is all async, so the ReplicationStream object is pinned, and won't let me move it out again to call the stop method.

I feel like I somehow need to pin the replication stream, but not pin the original client, which is only being held for type safety reasons.

I found one potential answer here, which is to use Box::pin rather than tokio::pin!(). I'm not sure that it solves my complete problem, but in case someone looks here that might be helpful.

Yeah, transfers of ownership typically involves a move, but you can avoid that if you box it.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.