From 092a2b89e03450d5cf182be938980afe191d6b27 Mon Sep 17 00:00:00 2001 From: Bharath Vissapragada Date: Mon, 5 Aug 2024 12:45:26 -0700 Subject: [PATCH] producer/request_state: make set_value() idempotent In some racy situations it may happen that the request is already errored out. Consider the following sequence of actions. replicate_f - succeeded but set_value() not called -- scheduling point -- term change -> sync() -> GC of inflight requests, request is marked timedout now set_value() is called in the original fiber, this triggers an assert. Relaxing the assert condition to make it idempotent. Subsequent client retry of the request will be marked success (once the change is applied in the stm and the request state is populated). Unable to reproduce in a unit test mainly due to lack of an idempotent client in the unit test fixture. --- src/v/cluster/producer_state.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/v/cluster/producer_state.cc b/src/v/cluster/producer_state.cc index aaf06eadbb8ff..93e1fc41c5c6b 100644 --- a/src/v/cluster/producer_state.cc +++ b/src/v/cluster/producer_state.cc @@ -32,12 +32,10 @@ result_promise_t::future_type request::result() const { } void request::set_value(request_result_t::value_type value) { - vassert( - _state <= request_state::in_progress && !_result.available(), - "unexpected request state during result set: {}", - *this); - _result.set_value(value); - _state = request_state::completed; + if (_state != request_state::completed) { + _result.set_value(value); + _state = request_state::completed; + } } void request::set_error(request_result_t::error_type error) {