FAQ

Why does the client-side middleware use Arc?

If you’ve paid close attention, you’d notice that in the generated code on the client-side, we wrap the user-provided Req into Arc<Req> before actually executing the volo_thrift client’s call method. However, on the server-side, we directly use Req.

The reason for this design is that the client-side requires more complex service governance logic compared to the server-side. Especially, some service governance logic conflicts with Rust’s ownership model. For instance, if a connection fails, we might need to retry on a different node or even implement more complex timeout-retry logic. If we were to directly use Req, once we execute the inner service’s call for the first time, the ownership would have already been moved, preventing us from implementing retry logic.

Additionally, using Arc helps us avoid problems caused by concurrent access under middleware (such as scenarios involving mirror/diff), without going into excessive detail here.

Furthermore, the client-side itself shouldn’t modify Req, hence eliminating the need for mutable access.

On the other hand, the server-side doesn’t have such complex usage scenarios, and ultimately, ownership needs to be passed to the user’s handler. Therefore, using Req ownership directly on the server-side suffices.

Why is the code generated by volo-cli separately split into the volo-gen crate?

This separation is because Rust’s compilation operates on a crate-by-crate basis. Creating the generated code as a separate crate allows for better utilization of the compile cache (IDL generally doesn’t change frequently).

How compatible is it with Kitex?

Volo is fully compatible with Kitex, including functionalities like metadata transmission.