Skip to content

Commit

Permalink
Merge branch 'master' of github.com:pavelbezpravel/seastar into devco…
Browse files Browse the repository at this point in the history
…ntainer
  • Loading branch information
pavelbezpravel committed Jun 12, 2024
2 parents 9bfff81 + 6c14779 commit 6ea987c
Show file tree
Hide file tree
Showing 11 changed files with 691 additions and 346 deletions.
43 changes: 28 additions & 15 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
# syntax=docker/dockerfile:1

FROM ubuntu:mantic
RUN apt-get -y update
RUN apt-get -y install gnupg curl
RUN echo "deb http://apt.llvm.org/mantic/ llvm-toolchain-mantic-17 main" \
>> /etc/apt/sources.list.d/llvm.list
RUN echo "deb http://apt.llvm.org/mantic/ llvm-toolchain-mantic-18 main" \
>> /etc/apt/sources.list.d/llvm.list
RUN curl -sSL https://apt.llvm.org/llvm-snapshot.gpg.key -o /etc/apt/trusted.gpg.d/apt.llvm.org.asc
RUN apt -y update \
&& apt -y install build-essential \
&& apt -y install gcc-12 g++-12 gcc-13 g++-13 pandoc \

RUN --mount=type=bind,source=./install-dependencies.sh,target=./install-dependencies.sh \
apt-get update && apt-get install -y \
curl \
gnupg \
&& echo "deb http://apt.llvm.org/mantic/ llvm-toolchain-mantic-17 main" \
>> /etc/apt/sources.list.d/llvm.list \
&& echo "deb http://apt.llvm.org/mantic/ llvm-toolchain-mantic-18 main" \
>> /etc/apt/sources.list.d/llvm.list \
&& curl -sSL https://apt.llvm.org/llvm-snapshot.gpg.key -o /etc/apt/trusted.gpg.d/apt.llvm.org.asc \
&& apt-get update && apt-get install -y \
build-essential \
clang-17 \
clang-18 \
clang-tools-18 \
gcc-12 \
g++-12 \
gcc-13 \
g++-13 \
pandoc \
&& update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 12 \
&& update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 12 \
&& update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 13 \
&& update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 13 \
&& apt -y install clang-17 clang-18 clang-tools-18 \
&& update-alternatives --install /usr/bin/clang clang /usr/bin/clang-17 17 \
&& update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-17 17 \
&& update-alternatives --install /usr/bin/clang clang /usr/bin/clang-18 18 \
&& update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-18 18
COPY install-dependencies.sh /tmp/
RUN bash /tmp/install-dependencies.sh
CMD /bin/bash
&& update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-18 18 \
&& bash ./install-dependencies.sh \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

CMD ["/bin/bash"]
49 changes: 46 additions & 3 deletions include/seastar/http/client.hh
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public:
future<> close();

private:
future<reply_ptr> do_make_request(request rq);
future<reply_ptr> do_make_request(request& rq);
void setup_request(request& rq);
future<> send_request_head(const request& rq);
future<reply_ptr> maybe_wait_for_continue(const request& req);
Expand Down Expand Up @@ -166,6 +166,11 @@ public:
*/

class client {
public:
using reply_handler = noncopyable_function<future<>(const reply&, input_stream<char>&& body)>;
using retry_requests = bool_class<struct retry_requests_tag>;

private:
friend class http::internal::client_ref;
using connections_list_t = bi::list<connection, bi::member_hook<connection, typename connection::hook_t, &connection::_hook>, bi::constant_time_size<false>>;
static constexpr unsigned default_max_connections = 100;
Expand All @@ -174,20 +179,27 @@ class client {
unsigned _nr_connections = 0;
unsigned _max_connections;
unsigned long _total_new_connections = 0;
const retry_requests _retry;
condition_variable _wait_con;
connections_list_t _pool;

using connection_ptr = seastar::shared_ptr<connection>;

future<connection_ptr> get_connection();
future<connection_ptr> make_connection();
future<> put_connection(connection_ptr con);
future<> shrink_connections();

template <std::invocable<connection&> Fn>
auto with_connection(Fn&& fn);

template <typename Fn>
requires std::invocable<Fn, connection&>
auto with_new_connection(Fn&& fn);

future<> do_make_request(connection& con, request& req, reply_handler& handle, std::optional<reply::status_type> expected);

public:
using reply_handler = noncopyable_function<future<>(const reply&, input_stream<char>&& body)>;
/**
* \brief Construct a simple client
*
Expand Down Expand Up @@ -220,9 +232,37 @@ public:
* may re-use the sockets on its own
*
* \param f -- the factory pointer
* \param max_connections -- maximum number of connection a client is allowed to maintain
* (both active and cached in pool)
* \param retry -- whether or not to retry requests on connection IO errors
*
* The client uses connections provided by factory to send requests over and receive responses
* back. Once request-response cycle is over the connection used for that is kept by a client
* in a "pool". Making another http request may then pick up the existing connection from the
* pool thus avoiding the extra latency of establishing new connection. Pool may thus accumulate
* more than one connection if user sends several requests in parallel.
*
* HTTP servers may sometimes want to terminate the connections it keeps. This can happen in
* one of several ways.
*
* The "gentle" way is when server adds the "connection: close" header to its response. In that
* case client would handle the response and will just close the connection without putting it
* to pool.
*
* Less gentle way a server may terminate a connection is by closing it, so the underlying TCP
* stack would communicate regular TCP FIN-s. If the connection happens to be in pool when it
* happens the client would just clean the connection from pool in the background.
*
* Sometimes the least gentle closing occurs when server closes the connection on the fly and
* TCP starts communicating FIN-s in parallel with client using it. In that case, user would
* receive exception from the \ref make_request() call and will have to do something about it.
* Client provides a transparent way of handling it called "retry".
*
* When enabled, it makes client catch the transport error, close the broken connection, open
* another one and retry the very same request one more time over this new connection. If the
* second attempt fails, this error is reported back to user.
*/
explicit client(std::unique_ptr<connection_factory> f, unsigned max_connections = default_max_connections);
explicit client(std::unique_ptr<connection_factory> f, unsigned max_connections = default_max_connections, retry_requests retry = retry_requests::no);

/**
* \brief Send the request and handle the response
Expand All @@ -236,6 +276,9 @@ public:
* \param handle -- the response handler
* \param expected -- the optional expected reply status code, default is std::nullopt
*
* Note that the handle callback should be prepared to be called more than once, because
* client may restart the whole request processing in case server closes the connection
* in the middle of operation
*/
future<> make_request(request req, reply_handler handle, std::optional<reply::status_type> expected = std::nullopt);

Expand Down
Loading

0 comments on commit 6ea987c

Please sign in to comment.