Skip to content

Low-level pull mode API #2901

Open
Open
@hh9527

Description

@hh9527

PROS

  • Low level, user code has the full flow-control, spawn free in hyper level
  • How-to/When-to use spawn could be full decided by the user level code
    • Connection Level
    • Stream Level
    • Stream with upgrading
    • Request Level
  • Easy to implement a full-controllable graceful shutdown
    • Listener Level
    • Connection level
    • Stream Level
  • Easy to implement priority control for user code
  • Easy to implement memory/resource/number-of-tasks control for user code
  • Possible to let user level code to known response has been sent.

CONS

  • Maybe low level too much

Example

async fn main() -> Result<()> {
    let mut listener = TcpListener::bind(...).await?;
    while let Ok((conn, _)) = listener.accept().await {
        // wrap low-level connection into http connection
        let conn = HttpProtocol::new(conn).await?;

        // stream could be h1/h2 or h3 someday, for h1: each conn yield only one stream
        while let Some(http_stream) = conn.next().await {
            handle_stream(http_stream?).await.ok();
        }
    }
    Ok(())
}

async fn handle_stream(stream: HttpStream) -> Result<()> {
    let (mut input, mut output) = http_stream.split();

    // pull a new request
    // we know that request is one-by-one inside a stream
    while let Some(item) = input.next().await {
        // key could be used to ensure request/response is matched (Eg. no re-order)
        // key is cheap to Clone, maybe Copy
        let (key, req) = item?;

        // handle upgrade if upgradable
        if key.is_upgradable() {
            let stream = output.upgrade(input, key, ...).await?; // consume input & output, into stream
            return handle_upgraded_stream(stream).await;
        }

        // handle request
        let res = handle_request(req).await;

        // now, we have the opportunity to know that reply has been sent
        let now = Instant::now();
        output.send((key, res)).await?;
        eprintln!("reply time: {:?}", now.elapsed());
    }

    Ok(())
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    B-rfcBlocked: More comments would be useful in determine next steps.C-featureCategory: feature. This is adding a new feature.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions