Repository: envoyproxy/envoy
File: source/extensions/common/aws/metadata_credentials_provider_base.cc (C++)

Code before:
MetadataCredentialsProviderBase::MetadataCredentialsProviderBase(
    Server::Configuration::ServerFactoryContext& context, AwsClusterManagerPtr aws_cluster_manager,
    absl::string_view cluster_name, CreateMetadataFetcherCb create_metadata_fetcher_cb,
    MetadataFetcher::MetadataReceiver::RefreshState refresh_state,
    std::chrono::seconds initialization_timer)
    : context_(context), create_metadata_fetcher_cb_(create_metadata_fetcher_cb),
      cluster_name_(cluster_name), cache_duration_(getCacheDuration()),
      refresh_state_(refresh_state), initialization_timer_(initialization_timer),
      aws_cluster_manager_(aws_cluster_manager) {

  // Set up metadata credentials statistics
  scope_ = context_.api().rootScope().createScope(
      fmt::format("aws.metadata_credentials_provider.{}.", cluster_name_));
  stats_ = std::make_shared<MetadataCredentialsProviderStats>(MetadataCredentialsProviderStats{
      ALL_METADATACREDENTIALSPROVIDER_STATS(POOL_COUNTER(*scope_), POOL_GAUGE(*scope_))});
  stats_->metadata_refresh_state_.set(uint64_t(refresh_state_));

  tls_slot_ =
      ThreadLocal::TypedSlot<ThreadLocalCredentialsCache>::makeUnique(context_.threadLocal());

  tls_slot_->set(
      [&](Event::Dispatcher&) { return std::make_shared<ThreadLocalCredentialsCache>(); });
};

MetadataCredentialsProviderBase::~MetadataCredentialsProviderBase() {
  auto fetcher = std::move(metadata_fetcher_);
  if (fetcher) {
    // If we're on the main thread, cancel directly
    if (context_.mainThreadDispatcher().isThreadSafe()) {
      fetcher->cancel();
    } else {
      // Post cleanup to main thread
      context_.mainThreadDispatcher().post([fetcher = std::move(fetcher)]() { fetcher->cancel(); });
    }
  }
}

void MetadataCredentialsProviderBase::onClusterAddOrUpdate() {
  ENVOY_LOG(debug, "Received callback from aws cluster manager for cluster {}", cluster_name_);
  if (!cache_duration_timer_) {
    std::weak_ptr<MetadataCredentialsProviderStats> weak_stats = stats_;
    std::weak_ptr<MetadataCredentialsProviderBase> weak_self = shared_from_this();
    cache_duration_timer_ =
        context_.mainThreadDispatcher().createTimer([weak_stats, weak_self]() -> void {
          if (auto stats = weak_stats.lock()) {
            stats->credential_refreshes_performed_.inc();
          }
          if (auto self = weak_self.lock()) {
            self->refresh();
          }
        });

Review comment (suggestion):
You should reset the original pointer since C++ doesn't guarantee it's valid after move.
Also, by posting to another thread, you are introducing a race, where fetch might succeed after `this` is destructed. You probably want to stop it before posting.

Code after:
MetadataCredentialsProviderBase::MetadataCredentialsProviderBase(
    Server::Configuration::ServerFactoryContext& context, AwsClusterManagerPtr aws_cluster_manager,
    absl::string_view cluster_name, CreateMetadataFetcherCb create_metadata_fetcher_cb,
    MetadataFetcher::MetadataReceiver::RefreshState refresh_state,
    std::chrono::seconds initialization_timer)
    : context_(context), create_metadata_fetcher_cb_(create_metadata_fetcher_cb),
      cluster_name_(cluster_name), cache_duration_(getCacheDuration()),
      refresh_state_(refresh_state), initialization_timer_(initialization_timer),
      aws_cluster_manager_(aws_cluster_manager) {

  // Set up metadata credentials statistics
  scope_ = context_.api().rootScope().createScope(
      fmt::format("aws.metadata_credentials_provider.{}.", cluster_name_));
  stats_ = std::make_shared<MetadataCredentialsProviderStats>(MetadataCredentialsProviderStats{
      ALL_METADATACREDENTIALSPROVIDER_STATS(POOL_COUNTER(*scope_), POOL_GAUGE(*scope_))});
  stats_->metadata_refresh_state_.set(uint64_t(refresh_state_));

  tls_slot_ =
      ThreadLocal::TypedSlot<ThreadLocalCredentialsCache>::makeUnique(context_.threadLocal());

  tls_slot_->set(
      [&](Event::Dispatcher&) { return std::make_shared<ThreadLocalCredentialsCache>(); });
};

MetadataCredentialsProviderBase::~MetadataCredentialsProviderBase() {
  if (metadata_fetcher_) {
    metadata_fetcher_->cancel();
  }
}

void MetadataCredentialsProviderBase::onClusterAddOrUpdate() {
  ENVOY_LOG(debug, "Received callback from aws cluster manager for cluster {}", cluster_name_);
  if (!cache_duration_timer_) {
    std::weak_ptr<MetadataCredentialsProviderStats> weak_stats = stats_;
    std::weak_ptr<MetadataCredentialsProviderBase> weak_self = shared_from_this();
    cache_duration_timer_ =
        context_.mainThreadDispatcher().createTimer([weak_stats, weak_self]() -> void {
          if (auto stats = weak_stats.lock()) {
            stats->credential_refreshes_performed_.inc();
          }
          if (auto self = weak_self.lock()) {
            self->refresh();
          }
        });
  }
  if (!cache_duration_timer_->enabled()) {
    cache_duration_timer_->enableTimer(std::chrono::milliseconds(1));
  }
}

void MetadataCredentialsProviderBase::credentialsRetrievalError() {