1
0
mirror of https://github.com/esphome/esphome.git synced 2025-06-15 14:56:59 +02:00

Improve shutdown reliability when tx buffer is full (#9043)

This commit is contained in:
J. Nick Koston 2025-06-11 05:08:23 -05:00 committed by GitHub
parent 3411e45a0a
commit e8aa7cff36
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 18 additions and 2 deletions

View File

@ -1886,6 +1886,12 @@ uint16_t APIConnection::try_send_list_info_done(EntityBase *entity, APIConnectio
return encode_message_to_buffer(resp, ListEntitiesDoneResponse::MESSAGE_TYPE, conn, remaining_size, is_single); return encode_message_to_buffer(resp, ListEntitiesDoneResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
} }
uint16_t APIConnection::try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single) {
DisconnectRequest req;
return encode_message_to_buffer(req, DisconnectRequest::MESSAGE_TYPE, conn, remaining_size, is_single);
}
uint16_t APIConnection::get_estimated_message_size(uint16_t message_type) { uint16_t APIConnection::get_estimated_message_size(uint16_t message_type) {
// Use generated ESTIMATED_SIZE constants from each message type // Use generated ESTIMATED_SIZE constants from each message type
switch (message_type) { switch (message_type) {
@ -2021,6 +2027,8 @@ uint16_t APIConnection::get_estimated_message_size(uint16_t message_type) {
return ListEntitiesServicesResponse::ESTIMATED_SIZE; return ListEntitiesServicesResponse::ESTIMATED_SIZE;
case ListEntitiesDoneResponse::MESSAGE_TYPE: case ListEntitiesDoneResponse::MESSAGE_TYPE:
return ListEntitiesDoneResponse::ESTIMATED_SIZE; return ListEntitiesDoneResponse::ESTIMATED_SIZE;
case DisconnectRequest::MESSAGE_TYPE:
return DisconnectRequest::ESTIMATED_SIZE;
default: default:
// Fallback for unknown message types // Fallback for unknown message types
return 24; return 24;

View File

@ -426,6 +426,10 @@ class APIConnection : public APIServerConnection {
static uint16_t try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, static uint16_t try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single); bool is_single);
// Method for DisconnectRequest batching
static uint16_t try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
// Helper function to get estimated message size for buffer pre-allocation // Helper function to get estimated message size for buffer pre-allocation
static uint16_t get_estimated_message_size(uint16_t message_type); static uint16_t get_estimated_message_size(uint16_t message_type);

View File

@ -496,11 +496,15 @@ void APIServer::on_shutdown() {
this->socket_ = nullptr; this->socket_ = nullptr;
} }
// Change batch delay to 5ms for quick flushing during shutdown
this->batch_delay_ = 5;
// Send disconnect requests to all connected clients // Send disconnect requests to all connected clients
for (auto &c : this->clients_) { for (auto &c : this->clients_) {
if (!c->send_message(DisconnectRequest())) { if (!c->send_message(DisconnectRequest())) {
// If we can't send the disconnect request, mark for immediate closure // If we can't send the disconnect request directly (tx_buffer full),
c->next_close_ = true; // schedule it in the batch so it will be sent with the 5ms timer
c->schedule_message_(nullptr, &APIConnection::try_send_disconnect_request, DisconnectRequest::MESSAGE_TYPE);
} }
} }
} }