-
-
Notifications
You must be signed in to change notification settings - Fork 385
Description
It becomes clear that in order to be more useful for application developers, it's best to support async operation in the transport and protocol layers. This issue tracks the overall progress in making this conversion from blocking code to non-blocking/async code.
- git-packetline
- git-transport
- git-protocol
- gitoxide-core + gitoxide
- create discussion in
blocking
to figure out if we can haveblocking::spawn(future)
to avoid clumsy code and overhead.
Potential improvements
- get rid of unsafe pointer magic WithSidebands (cost: high)
- What needs to be done is to transform the
&mut StreamingPeekableIter
into a child future, and when exhausted, it must be transformed back into the&mut _
that created it. That way, only a single mutable reference to said Iter is present at any time. Unfortunately the generated futures (usingasync
) don't support that as we would have to keep both the future and the parent that created it inside of our own struct. Instead of hiding this using pointers, one could implement the magical part by hand, a custom future, which happily dissolves into its mutable parent iter ref. That would be quite some work though.
- What needs to be done is to transform the
Requirements
git-transport
viaquinn
- how would that work? Maybe async http isn't even necessary?- must support tokio 1.0 (
quinn
needs it).surf
viahyper
seems to be locked to tokio 0.2 (even though async-std supports tokio 1.0 as well.
Research
- maybe-async - conditional compilation of both sync and async APIs
- Useful to keep the sync version which compiles quickly thanks to libcurl used under the hood. This might allow to write the async version in smaller increments.
- async-http(s) client
- Abstracting over the runtime can be done by…knowing which one to use. Sync and async selection can be done with
maybe-async
. tokio
- comes with its own compatibility layer to adapt to
futures::io
related traits. - has its own non-blocking process implementation.
- comes with its own compatibility layer to adapt to
Maybe_async
As it's async by default which requires more dependencies than sync code it won't be used in crates to avoid pulling in unnecessary dependencies for builds that don't use it.
This also means definitive duplicates here and there for IO code that otherwise could be deduplicated with maybe_async.
However, tests can and should benefit from maybe_async as minimal dependencies are less important there. Thus we deduplicate tests with it to assure there is no drift in code. This rightfully assumes decent test coverage.
Related
- Can maybe_async get an
is_async
feature toggle? - See if futures-lite::BlockOn can be used instead by now.
Out of Scope
- async server
Archive
- Figure out how git-transport could be used with
quinn
and other custom transports.quinn
streams support bothtokio
andfutures
AsyncReadWrite traits, so going with the more general trait at first should be good. Probably it's a good idea to have a redirection for traits so replacing them with the tokio version is easier should it ever be required.
- Navigate the crate ecosystem and find an http client that can work.
- Surf with lib-curl as backend seems to do it, as it uses future::io traits which are actually most compatible.
- Realize that what's really needed is a 'custom async transport' and not do all of the following (as originally intended) unless this comes up again.
- async client
- maybe::async transport
surf
based http backend with feature toggles to allow backend selection. This allows choosing the runtime.- assure enough tests for these new feature toggles.
- maybe::async protocol
- maybe::async
gixp clone
path - this represents the application and is a good example on how the API feels, alongside the blocking implementation.
- maybe::async transport
- async client
- Research what it would mean to have an async transport trait and how it could fit
- goal put everything that's currently availabe into
client::blocking
and start working with maybe_async to pull thegit::Connection
into async land, step by step, also using maybe_async. This has a feature-toggle-able ripple effect and hides all other blocking implementations (as the trait is either blocking or async) until these are ported. Generally thegit-transport
crate will only support one mode at a time.
- goal put everything that's currently availabe into
- git-packetline ✓
- the grand refactor - it always felt a little off
- feature toggles for 'blocking' mode, with default to async operation like in
git-transport/protocol
- refactor packet line provider
- feature toggle for turning on async-io - otherwise blocking io MUST pull in futures-io for no reason. This will propagate but it's OK.
- async encode needed for Writer
- async low level line writer (new)
- async higher level line writer
- try to unify encode tests using maybe_async as test-utility only
- async encode
- immutable packet line IO
- async packet line provider (easy mode)
- async sideband reader (no easy mode)
- figure out how to use easy mode packet line provider from no-easy-mode (aka async-futures from poll based
- git-transport
- async test case - empty, but at least we can compile something
- async capabilities
- remove maybe_async from library code and add async-client trait behind feature toggle
- move everything without IO ties into shared space
Capabilities::from_lines_with_version_detection(…)
- Handshake V1 tests
- decode an actual pack from an async-read - show how to translate it into the blocking world to combine async and sync
- TransportExt trait
- Handshake V2 tests
- Show how to read a pack while keeping everything async
- unblock handshake v2 test when traversing entries.
- git-protocol
- separate common (no feature toggles needed) tests and those who need feature toggles
- git-credentials - keep it blocking as async programs aren't really a thing and the
blocking
crate exists. - start out moving everything into 'blocking' module to be able to take on asyncification step-by-step
- async arguments and command
- Refs parsing in async
- Response in async
- async Delegate
- use maybe_async and disallow --all-features as it would misconfigure maybe-async
- async
fetch(…)
- remove
#[allow(dead_code)]
in async mode - crate-features.md update
- refactor
- disallow all client features enabled in
git-transport
- disallow all client features enabled in
git-packetline
- disallow all client features enabled in
- gitoxide-core + gitoxide
- feature toggle for blocking client, none set means no networking
- feature toggle for async client
- don't let blocking client take precedence in gitoxide-core
- async transport creation
- async LsRemote delegate impl + journey test
- async PackReceive delegate impl
- Is there an easy way to unblock the pack writing?
- journey test for async client receiving a pack from a git daemon using async io + fix TODO