-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
send &mut #9
Comments
I'd actually say that it's natural for a The same holds for example for If you want to write and read at the same time, you can split the socket, which divides it into two halves - one for reading and one for writing. There are multiple ways of achieving that, we provide a If you just want to share the socket amongst multiple borrowers and you only write with one at the same time, a canonical solution for that is probably using something akin to |
The The socket can only be used by one task at one time. If I have multiple tasks that all required to send/receive to the same socket I have either used |
I don't have code I can easily share on hand, but if I get some time I can try to come up with a minimal example. Core of it though is a webservice that needs to send events to a zero PUSH socket to be logged. There can be many parallel requests to the service generating events. As far as I understood there wasn't a recieve/read side of a PUSH socket, and since the version with it isn't published yet I was sorta floundering around the docs (note to self, I should generate them locally). It seemed like PUSH should just be write and intuitively it seemed like a black hole. If you successfully sent the message to the socket, that was it, which made it weird that it required mut to send. I guess I was expecting behaviour closer to what the Right now I am going forward with something like (psuedocode):
and threading the sender through a bunch of the logic in each service. Just felt like the |
Beware that ZeroMQ is by design NOT thread safe, so it's not safe to send ZMQ sockets between threads (you can avoid this by using a single threaded tokio runtime). If you just want to have multiple shared references to the socket without going across threads and you don't want to use |
I think the challenge here is that ZeroMQ & tokio are doing similar things and can step on eachother's toes like you have found. Sometimes it's not clear when to use one or the other. ZeroMQ was definitely not designed in a time when rust was a thing, and probably wayyy before async/futures was considered. The sockets from ZeroMQ are unfortunately not threadsafe, i.e, you can't have 2 or more threads sending data at the same time. In rust parlance they are There are a few options here that I can think of alongside @Kobzol's solution, but no silver bullet: Firstly, keep it simple & run everything single threaded. The current client_worker example does this (but is changed in the PR I have active). The Secondly, you could have multiple sockets connecting to the same endpoint. I'm not sure what the overhead would be, especially if you have lots of tasks running, but maybe Thirdly, you can use sync primitives inside tokio to assist with this. You have already stumbled upon If you don't want the memory requirements of an mpsc, you could instead use a tokio Mutex. Not to be confused with a std mutex: the My rule of thumb is to use tmq at the edge, and use tokio for any internal task related communications. This means that your solution of using an mpsc is going to work, but obviously has some tradeoffs for memory, whereas the mutex would not buffer up messages itself. We could provide some wrapper types but they would still be using tokio primitives, and the challenge would be to ensure that they are performant and do what the API consumer would expect. |
Makes sense, though it's too bad. Thanks for all the context and clarification. It may make sense for this library to present some of these patterns itself, since it's specifically tmq. You're right that the challenge would be making them performant and ergonomic, but that's going to be a challenge that anyone solving a problem with those primitives and the library will need to figure out too. May help solve a lot of people's average cases by having some compositions of the tokio primitives with sockets in the lib, with the ability to then document the tradeoffs and use cases. Either way you've both been very helpful, thank you. |
I'll keep this issue open as a possible enhancement to tmq |
May I conclude that Rationale:
I obtain the following
|
So the sockets are See jobq for an example |
I've been trying to understand the code but the macros keep throwing me for a loop. Why does
send
requiremut
? Is there any way to prevent that?It's leading to some pretty awkward code where I create an
mpsc
channel to share the socket across async stuff. It intuitively feels like I should be able to share the socket as is and send to it without adding the additional in memory channel.The text was updated successfully, but these errors were encountered: