Connection agnostic crates #31
Comments
The fact that these types are different is not what prevents the two crates from sharing code. Their implementations are fundamentally and significantly different. |
@sfackler I'm not familiar with the codebase, however do you think that when using a generic connection type, like proposed, the code base could share more code? For example I've writing a client libary with Redis to experiment with this idea. It uses a future like pattern where a |
hyper has done this for a while: it works with any transport type that is |
Nothing is preventing it from using a generic connection type right now! It wouldn't enable any more code reuse between the async and sync implementations, at least as currently designed. |
I'm not quite sure what you mean here, but I think it effectively makes everything async (or at least as difficult to code as async, in terms of managing internal states with partial IO). But postgres (or whatever) would need to handle it internally - the user of the postgres crate couldn't do it without knowing postgres's internal state. (If postgres gets a partial response from the socket and returns WouldBlock to its caller, what does it do with that partial response? What's the caller supposed to do with the WouldBlock?) |
@jsgf When it reads a partial response it would store that in a bytes buffer, e.g. In case of blocking I/O most of them don't return partial responses, they return whatever is currently is in the buffer or blocking until something is written into it. That means that if only a part of a response is read the crate needs to call read again, which then blocks again. For example: say when have Postgres client which sends an request. Then Postgres response with only half of the response initially. The client can then read the first half of the request and start parsing it. If it can't deal with partial requests it can just call read again and block until the entire request in read into a buffer. |
Currently most crates use a concrete type for connections, often
std::net::TcpStream
, but to support async I/O often a different connection type is need, e.g.tokio::net::TcpStream
.For example take the
postgres
crate, which usesstd::net::TcpStream
for blocking I/O. But to support async I/Otokio-postgres
was created which usestokio::net::TcpStream
.I think it would be worthwhile to create a generic
Connection
trait, which crates likepostgres
(but also e.g.hyper
) can use as an abstract connection type. This can be used for both blocking and async I/O, wherestd::io::ErrorKind::WouldBlock
errors are handled by the user of the crate.This has two advantages:
Future
s.TcpStream
, but so does Mio and so does the standard libary. Supporting a single generic connection type would support also three those types with the same code (assuming they implement the correct trait).Possible design
A simple design would be the following.
And add documentation that the
Connection
can returnstd::io::ErrorKind::WouldBlock
which isn't really an error and the crate must gracefully handle it.This assumes that calling
read
/write
on a concrete type does wake itself when it returnsWouldBlock
, in the context of using futures. I believe this already the case for both Tokio and mio.Future-io's AsyncRead and AsyncWrite
For async I/O the
futures-io
crate provides special read and write traits that hook into the task system. These trait could also be used rather thenRead
andWrite
. The downside of this is that blocking I/O won't be supported anymore.Thoughts?
The text was updated successfully, but these errors were encountered: