|
|
|
@ -36,15 +36,15 @@ |
|
|
|
|
#include "src/core/lib/channel/channel_args.h" |
|
|
|
|
#include "src/core/lib/gprpp/debug_location.h" |
|
|
|
|
#include "src/core/lib/gprpp/ref_counted_ptr.h" |
|
|
|
|
#include "src/core/lib/gprpp/status_helper.h" |
|
|
|
|
#include "src/core/lib/gprpp/work_serializer.h" |
|
|
|
|
#include "src/core/lib/iomgr/exec_ctx.h" |
|
|
|
|
#include "src/core/lib/iomgr/timer.h" |
|
|
|
|
#include "src/core/lib/service_config/service_config.h" |
|
|
|
|
#include "src/core/lib/uri/uri_parser.h" |
|
|
|
|
|
|
|
|
|
namespace grpc_core { |
|
|
|
|
|
|
|
|
|
using ::grpc_event_engine::experimental::EventEngine; |
|
|
|
|
|
|
|
|
|
PollingResolver::PollingResolver(ResolverArgs args, |
|
|
|
|
const ChannelArgs& channel_args, |
|
|
|
|
Duration min_time_between_resolutions, |
|
|
|
@ -88,9 +88,7 @@ void PollingResolver::RequestReresolutionLocked() { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PollingResolver::ResetBackoffLocked() { |
|
|
|
|
if (have_next_resolution_timer_) { |
|
|
|
|
grpc_timer_cancel(&next_resolution_timer_); |
|
|
|
|
} |
|
|
|
|
MaybeCancelNextResolutionTimer(); |
|
|
|
|
backoff_.Reset(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -99,30 +97,46 @@ void PollingResolver::ShutdownLocked() { |
|
|
|
|
gpr_log(GPR_INFO, "[polling resolver %p] shutting down", this); |
|
|
|
|
} |
|
|
|
|
shutdown_ = true; |
|
|
|
|
if (have_next_resolution_timer_) { |
|
|
|
|
grpc_timer_cancel(&next_resolution_timer_); |
|
|
|
|
} |
|
|
|
|
MaybeCancelNextResolutionTimer(); |
|
|
|
|
request_.reset(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PollingResolver::OnNextResolution(void* arg, grpc_error_handle error) { |
|
|
|
|
auto* self = static_cast<PollingResolver*>(arg); |
|
|
|
|
self->work_serializer_->Run( |
|
|
|
|
[self, error]() { self->OnNextResolutionLocked(error); }, DEBUG_LOCATION); |
|
|
|
|
void PollingResolver::ScheduleNextResolutionTimer(const Duration& timeout) { |
|
|
|
|
RefCountedPtr<PollingResolver> self = Ref(); |
|
|
|
|
next_resolution_timer_handle_ = |
|
|
|
|
channel_args_.GetObject<EventEngine>()->RunAfter( |
|
|
|
|
timeout, [self = std::move(self)]() mutable { |
|
|
|
|
ApplicationCallbackExecCtx callback_exec_ctx; |
|
|
|
|
ExecCtx exec_ctx; |
|
|
|
|
auto* self_ptr = self.get(); |
|
|
|
|
self_ptr->work_serializer_->Run( |
|
|
|
|
[self = std::move(self)]() { self->OnNextResolutionLocked(); }, |
|
|
|
|
DEBUG_LOCATION); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PollingResolver::OnNextResolutionLocked(grpc_error_handle error) { |
|
|
|
|
void PollingResolver::OnNextResolutionLocked() { |
|
|
|
|
if (GPR_UNLIKELY(tracer_ != nullptr && tracer_->enabled())) { |
|
|
|
|
gpr_log(GPR_INFO, |
|
|
|
|
"[polling resolver %p] re-resolution timer fired: error=\"%s\", " |
|
|
|
|
"shutdown_=%d", |
|
|
|
|
this, StatusToString(error).c_str(), shutdown_); |
|
|
|
|
"[polling resolver %p] re-resolution timer fired: shutdown_=%d", |
|
|
|
|
this, shutdown_); |
|
|
|
|
} |
|
|
|
|
have_next_resolution_timer_ = false; |
|
|
|
|
if (error.ok() && !shutdown_) { |
|
|
|
|
next_resolution_timer_handle_.reset(); |
|
|
|
|
if (!shutdown_) { |
|
|
|
|
StartResolvingLocked(); |
|
|
|
|
} |
|
|
|
|
Unref(DEBUG_LOCATION, "retry-timer"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PollingResolver::MaybeCancelNextResolutionTimer() { |
|
|
|
|
if (next_resolution_timer_handle_.has_value()) { |
|
|
|
|
if (GPR_UNLIKELY(tracer_ != nullptr && tracer_->enabled())) { |
|
|
|
|
gpr_log(GPR_INFO, "[polling resolver %p] cancel re-resolution timer", |
|
|
|
|
this); |
|
|
|
|
} |
|
|
|
|
channel_args_.GetObject<EventEngine>()->Cancel( |
|
|
|
|
*next_resolution_timer_handle_); |
|
|
|
|
next_resolution_timer_handle_.reset(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PollingResolver::OnRequestComplete(Result result) { |
|
|
|
@ -188,10 +202,9 @@ void PollingResolver::GetResultStatus(absl::Status status) { |
|
|
|
|
// in a loop while draining the currently-held WorkSerializer.
|
|
|
|
|
// Also see https://github.com/grpc/grpc/issues/26079.
|
|
|
|
|
ExecCtx::Get()->InvalidateNow(); |
|
|
|
|
Timestamp next_try = backoff_.NextAttemptTime(); |
|
|
|
|
Duration timeout = next_try - Timestamp::Now(); |
|
|
|
|
GPR_ASSERT(!have_next_resolution_timer_); |
|
|
|
|
have_next_resolution_timer_ = true; |
|
|
|
|
const Timestamp next_try = backoff_.NextAttemptTime(); |
|
|
|
|
const Duration timeout = next_try - Timestamp::Now(); |
|
|
|
|
GPR_ASSERT(!next_resolution_timer_handle_.has_value()); |
|
|
|
|
if (GPR_UNLIKELY(tracer_ != nullptr && tracer_->enabled())) { |
|
|
|
|
if (timeout > Duration::Zero()) { |
|
|
|
|
gpr_log(GPR_INFO, "[polling resolver %p] retrying in %" PRId64 " ms", |
|
|
|
@ -200,9 +213,7 @@ void PollingResolver::GetResultStatus(absl::Status status) { |
|
|
|
|
gpr_log(GPR_INFO, "[polling resolver %p] retrying immediately", this); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Ref(DEBUG_LOCATION, "next_resolution_timer").release(); |
|
|
|
|
GRPC_CLOSURE_INIT(&on_next_resolution_, OnNextResolution, this, nullptr); |
|
|
|
|
grpc_timer_init(&next_resolution_timer_, next_try, &on_next_resolution_); |
|
|
|
|
ScheduleNextResolutionTimer(timeout); |
|
|
|
|
// Reset result_status_state_. Note that even if re-resolution was
|
|
|
|
|
// requested while the result-health callback was pending, we can
|
|
|
|
|
// ignore it here, because we are in backoff to re-resolve anyway.
|
|
|
|
@ -213,7 +224,7 @@ void PollingResolver::GetResultStatus(absl::Status status) { |
|
|
|
|
void PollingResolver::MaybeStartResolvingLocked() { |
|
|
|
|
// If there is an existing timer, the time it fires is the earliest time we
|
|
|
|
|
// can start the next resolution.
|
|
|
|
|
if (have_next_resolution_timer_) return; |
|
|
|
|
if (next_resolution_timer_handle_.has_value()) return; |
|
|
|
|
if (last_resolution_timestamp_.has_value()) { |
|
|
|
|
// InvalidateNow to avoid getting stuck re-initializing this timer
|
|
|
|
|
// in a loop while draining the currently-held WorkSerializer.
|
|
|
|
@ -234,12 +245,7 @@ void PollingResolver::MaybeStartResolvingLocked() { |
|
|
|
|
this, last_resolution_ago.millis(), |
|
|
|
|
time_until_next_resolution.millis()); |
|
|
|
|
} |
|
|
|
|
have_next_resolution_timer_ = true; |
|
|
|
|
Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown").release(); |
|
|
|
|
GRPC_CLOSURE_INIT(&on_next_resolution_, OnNextResolution, this, nullptr); |
|
|
|
|
grpc_timer_init(&next_resolution_timer_, |
|
|
|
|
Timestamp::Now() + time_until_next_resolution, |
|
|
|
|
&on_next_resolution_); |
|
|
|
|
ScheduleNextResolutionTimer(time_until_next_resolution); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|