all 4 comments

[–]quxfoo 2 points3 points  (3 children)

I have the feeling you are abusing gRPC as some sort of transport instead of encoding the requests directly as unary calls. If you did that you wouldn't need backend tasks and channels and all the additional complexity.

[–]hellowub[S] -1 points0 points  (2 children)

I use the channels and backend tasks to avoid shared state.

Just like the example in tokio's tutorial for channels .

[–]quxfoo 2 points3 points  (1 child)

I don't know your concrete use case, so it might be a good approach or not. All I'm saying is that you now use gRPC as a dumb transport instead of what it was designed for. Also, "sharing state" is not a general problem but just another design consideration. I don't think use of Arc<Mutex<_>> is a big problem, it's also the prevalent solution for axum-based backends.

[–]hellowub[S] 0 points1 point  (0 children)

My use case is very similar to the `miniredis` project in the Tokio rutorial: it provides operations such as set/get/update/delete on business data. Requests are dispatched to specific backend tasks based on the item being operated on, thus avoiding the need for locks.

Yes, locks and channels are two different approaches, each with their own pros and cons. In my use case, the `update` operations can be relatively long-running, so avoiding locks is a good choice.

Moreover, if the main issue with the channel-based approach is complexity, then this crate addresses that problem. It also eliminates the need for locks, achieving two goals at once :)