Implement shutting down the write-side only

This commit is contained in:
2025-09-15 15:39:28 -04:00
parent 6b52c4289c
commit 55f6ebc02b
4 changed files with 37 additions and 21 deletions

View File

@@ -20,6 +20,15 @@
// Forward declaration
struct Server;
/**
* Shutdown modes for connection termination.
*/
enum class ConnectionShutdown {
None, // Normal operation - no shutdown requested
WriteOnly, // shutdown(SHUT_WR) after sending queued data
Full // close() after sending queued data
};
/**
* Base interface for sending messages to a connection.
* This restricted interface is safe for use by pipeline threads,
@@ -109,15 +118,14 @@ struct Connection : MessageSender {
*
* @param data_parts Span of string_views pointing to arena-allocated data
* @param arena Arena that owns all the memory referenced by data_parts
* @param close_after_send Whether to close connection after sending all
* queued data
* @param shutdown_mode Shutdown mode to apply after sending all queued data
*
* @note Thread Safety: Must be called from I/O thread only.
* @note Ordering: Bytes are sent in the order calls are made.
* @note The memory referenced by the data_parts span, must outlive @p arena.
* @note Close Request: To request connection close without sending data,
* pass empty data_parts span with close_after_send=true. This ensures
* all previously queued messages are sent before closing.
* @note Shutdown Request: To request connection shutdown without sending
* data, pass empty data_parts span with desired shutdown_mode. This ensures
* all previously queued messages are sent before shutdown.
*
* Example usage (from ConnectionHandler::on_preprocess_writes):
* ```cpp
@@ -125,11 +133,12 @@ struct Connection : MessageSender {
* auto parts = arena.allocate_span<std::string_view>(2);
* parts[0] = build_header(arena);
* parts[1] = build_body(arena);
* conn.append_bytes({parts, 2}, std::move(arena), false);
* conn.append_bytes({parts, 2}, std::move(arena), ConnectionShutdown::None);
* ```
*/
void append_bytes(std::span<std::string_view> data_parts, Arena arena,
bool close_after_send);
void
append_bytes(std::span<std::string_view> data_parts, Arena arena,
ConnectionShutdown shutdown_mode = ConnectionShutdown::None);
void send_response(void *protocol_context, std::string_view response_json,
Arena arena) override;
@@ -346,8 +355,9 @@ private:
// dropped while server accesses existing elements.
int64_t outgoing_bytes_queued_{0}; // Counter of queued bytes
std::deque<PendingResponse>
pending_response_queue_; // Responses awaiting protocol processing
bool close_requested_{false}; // True if close_after_send has been requested
pending_response_queue_; // Responses awaiting protocol processing
ConnectionShutdown shutdown_requested_{
ConnectionShutdown::None}; // Shutdown mode requested
// Set to a negative number in `close`
int fd_;