rustasync / runtime

Empowering everyone to build asynchronous software
https://docs.rs/runtime
Apache License 2.0
862 stars 28 forks source link

Design: separate networking from spawning futures #46

Closed najamelan closed 5 years ago

najamelan commented 5 years ago

I have been considering using runtime, but there are some issues with it's design. I wonder how you feel about them. It's common to spawn futures without using networking (TCP/UDP), especially in libraries which might have to spawn futures, but would leave the choice of executor to client code.

I am surprised by how tightly runtime is coupled to romio and networking. I don't really want to bloat library dependencies like this.

Have you considered separating the two concerns?

yoshuawuyts commented 5 years ago

If you want to use a specific executor, it's possible to write your own Runtime, and use unimplemented! for the methods you're not interested in. The result in the binary should be rather minimal.

If however you still consider this to be ill-fitting for your use case, it might be worth considering using an executor such as juliex directly.

The idea of Runtime is to provide a cohesive story for async Rust, but also providing flexibility and room for experimentation.

I hope this was helpful!

najamelan commented 5 years ago

So if I get it right, since network crates are a hard dependencies of runtime, it's not possible to use this for libraries that don't want to bloat dependencies unnecessarily?

asonix commented 5 years ago

I don't think saying runtime has a hard dependency on networking is a fair assessment. The only dependency on romio and juliex are in the runtime-native subcrate, which are exposed as a default, but optional feature. You can disable this feature and opt for the Tokio runtime provided by the runtime-tokio crate, or you can implement your own, lighter-weight runtime backend by disabling all of runtime's features and using the runtime-raw crate.

najamelan commented 5 years ago

Ah, thank you for pointing that out. I completely missed the feature in the main toml. I will look into making alternative runtimes then.

najamelan commented 5 years ago

Before @asonix pointed out my ignorance last night, I had already done most of the work for an alternative implementation of a runtime, and after considering making custom implementations for runtime I think I might continue the other crate, mainly because:

@yoshuawuyts It feels quite unidiomatic to me to use unimplemented in trait methods (turns compile time errors into runtime errors and does away with the concept of traits being contracts), when network and other methods could be provided by different traits that could be implemented for certain runtimes but not for others. When you want to add more and more features in the future, the risk exists as well that more and more unimplemented!() methods criss-cross the codebase, which might be unwieldy to use safely.

All that being said, I could make runtime-juliex, a copy of runtime-native, strip the dependencies and replace the network related method impls with unimplemented!(). Would you merge such a pull request?

yoshuawuyts commented 5 years ago

@najamelan If you build runtime-juliex I'd love to merge a PR to link to it from the docs! -- but if we merge code into this repo directly that means I'll then be co-responsible for maintaining it, and I don't really want to be on the hook for that, haha. I think you should just go ahead and publish it under your name!

najamelan commented 5 years ago

Thinking about it, it wouldn't be very DRY to copy over runtime-native and just strip out the networking deps/functionality. Would a feature flag not be better? I suppose it would mean putting a feature in runtime as well so it can depend on runtime-native with both network and without?

yoshuawuyts commented 5 years ago

@najamelan I think copying code in this case is the better option.