Skip to content

refactor(auth): use injected executor for token refresh - #1033

Open
wgtmac wants to merge 12 commits into
mainfrom
codex/oauth-refresh-executor
Open

wgtmac wants to merge 12 commits into
mainfrom
codex/oauth-refresh-executor

Conversation

@wgtmac

@wgtmac wgtmac commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Replace the auth-specific token refresh scheduler with an internal utility that shares one process-lifetime timer and submits due work through a caller-owned Executor.

  • Accept borrowed executors through RestCatalog::Make(config, client_factory, auth_executor, metrics_executor) and the optional final argument of AuthSession::MakeOAuth2. Without an auth executor, background refresh is disabled.
  • Keep cancellation and shutdown scoped to each scheduler. A single session control mutex serializes task installation and closing; HTTP and dispatch retries retain separate budgets.
  • Keep the shared timer alive during static destruction. Its process lifetime removes the need for global shutdown, self-ownership and join/detach layers.
  • Use file-local executor mocks and standard futures in tests. No new shared test helper, and no changes to the existing ThreadExecutor.

Validation:

  • REST tests: 484 passed, 1 existing skip. Scheduler tests: 6 passed, including static-destruction, cancellation/rejection, callback teardown and active-submit shutdown regressions.
  • Scheduler suite passed 20 shuffled ASAN/UBSAN repetitions; four key OAuth/catalog tests passed 30 shuffled repetitions.
  • Core/REST shared libraries built successfully. Repository clang-tidy checks (LLVM 21) and pre-commit passed.

Copilot AI balanced review requested due to automatic review settings October 17, 2026 16:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved linking, concurrency, scheduler lifetime, and refresh-dispatch issues block approval.

5 open issues
What changed in this PR

Moves OAuth token-refresh scheduling into a reusable internal utility that dispatches work through an injected executor.

Changes:

  • Replaces the auth-specific scheduler with ScheduledExecutor.
  • Adds optional executor injection; background refresh is disabled when omitted.
  • Migrates scheduler tests and updates build integration.
File Description
src/​iceberg/​util/​scheduled_executor.cc Implements delayed dispatch and cancellation.
src/​iceberg/​util/​scheduled_executor_internal.h Defines scheduler and task handles.
src/​iceberg/​test/​auth_manager_test.cc Migrates scheduler tests.
src/​iceberg/​cpp20_compatibility_internal.h Removes the deleted scheduler include.
src/​iceberg/​CMakeLists.txt Builds the new scheduler.
src/​iceberg/​catalog/​rest/​rest_catalog.h Exposes optional auth executor injection.
src/​iceberg/​catalog/​rest/​rest_catalog.cc Configures the auth manager’s executor.
src/​iceberg/​catalog/​rest/​CMakeLists.txt Removes the old scheduler source.
src/​iceberg/​catalog/​rest/​auth/​token_refresh_scheduler.h Deletes the old scheduler interface.
src/​iceberg/​catalog/​rest/​auth/​token_refresh_scheduler.cc Deletes the old scheduler implementation.
src/​iceberg/​catalog/​rest/​auth/​auth_session.h Documents refresh executor requirements.
src/​iceberg/​catalog/​rest/​auth/​auth_session.cc Passes the scheduler into session configuration.
src/​iceberg/​catalog/​rest/​auth/​auth_session_internal.h Adapts refresh scheduling and cancellation.
src/​iceberg/​catalog/​rest/​auth/​auth_manager.h Adds the executor configuration hook.
src/​iceberg/​catalog/​rest/​auth/​auth_manager.cc Creates and supplies the scheduler.

Review effort: Balanced

Comment thread src/iceberg/catalog/rest/auth/auth_manager.cc Outdated
Comment thread src/iceberg/catalog/rest/auth/auth_session_internal.h Outdated
Comment thread src/iceberg/util/scheduled_executor_internal.h Outdated
Comment thread src/iceberg/catalog/rest/auth/auth_manager.h
Comment thread src/iceberg/util/scheduled_executor.cc Outdated
Copilot AI balanced review requested due to automatic review settings October 18, 2026 01:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Scheduling and teardown races can stop refresh or terminate the process, while rejected submissions can cause a busy loop.

3 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Destruction order can invalidate callback state before worker joins

src/​iceberg/​test/​auth_manager_test.cc:704

Shutdown() now joins only the timer thread, not executor workers. A worker can set fired and pause before cv.notify_one(); the waiting thread can observe fired and finish the test, destroying cv before ThreadExecutor's destructor joins that worker. Declare the callback state before the executor so its workers are joined before their captured objects are destroyed.

5 resolved since last review

Review effort: Balanced

Comment thread src/iceberg/catalog/rest/auth/auth_session_internal.h Outdated
Comment thread src/iceberg/util/scheduled_executor.cc Outdated
Comment thread src/iceberg/catalog/rest/auth/auth_session_internal.h Outdated
Copilot AI balanced review requested due to automatic review settings October 18, 2026 01:37

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The asynchronous scheduling and shared-lifetime teardown changes need human validation before approval.

3 open issues

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 18, 2026 02:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Executor rejection recovery resets HTTP retry state, allowing failing token requests to bypass the retry limit indefinitely.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Rejected refresh retries reset attempts and bypass the retry limit

src/​iceberg/​catalog/​rest/​auth/​auth_session_internal.h:242

When submission of an HTTP retry is rejected, this handler reschedules through ScheduleRefreshAfter(), whose callback calls DoRefresh() and resets the HTTP attempt counter to zero. Alternating accepted and rejected submissions while token requests fail can therefore bypass kMaxRetries indefinitely. Retry dispatch of the pending DoRefreshAttempt, preserving its attempt, backoff, and refresh_started_at, while retaining the bounded dispatch-retry backoff.

3 resolved since last review

Review effort: Balanced

@wgtmac
wgtmac marked this pull request as ready for review October 19, 2026 07:37
Copilot AI balanced review requested due to automatic review settings October 19, 2026 15:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

5 open issues

Review effort: Lite

Comment thread src/iceberg/catalog/rest/rest_catalog.h
Comment thread src/iceberg/util/scheduled_executor.cc Outdated
Comment thread src/iceberg/util/scheduled_executor.cc Outdated
Comment thread src/iceberg/util/scheduled_executor.cc Outdated
Comment thread src/iceberg/util/scheduled_executor.cc
Copilot AI balanced review requested due to automatic review settings October 19, 2026 15:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/iceberg/catalog/rest/rest_catalog.h
Comment thread src/iceberg/util/scheduled_executor.cc Outdated
Comment thread src/iceberg/util/scheduled_executor.cc
Comment thread src/iceberg/util/scheduled_executor.cc Outdated
Comment thread src/iceberg/util/scheduled_executor.cc
Comment thread src/iceberg/util/scheduled_executor_internal.h Outdated
Copilot AI balanced review requested due to automatic review settings October 19, 2026 15:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

14 open issues

Review effort: Lite

Comment thread src/iceberg/catalog/rest/rest_catalog.h
Comment thread src/iceberg/util/scheduled_executor.cc
Comment thread src/iceberg/util/scheduled_executor_internal.h Outdated
Copilot AI balanced review requested due to automatic review settings October 19, 2026 16:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

18 open issues

Review effort: Lite

Comment thread src/iceberg/catalog/rest/rest_catalog.h
Comment thread src/iceberg/util/scheduled_executor.cc Outdated
Comment thread src/iceberg/util/scheduled_executor.cc
Comment thread src/iceberg/util/scheduled_executor_internal.h Outdated
Copilot AI balanced review requested due to automatic review settings October 19, 2026 16:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

21 open issues

And 1 more that still need to be addressed.

Review effort: Lite

Comment thread src/iceberg/catalog/rest/rest_catalog.h
Comment thread src/iceberg/util/scheduled_executor.cc
Comment thread src/iceberg/util/scheduled_executor.cc
Comment thread src/iceberg/catalog/rest/auth/auth_session_internal.h Outdated
Copilot AI balanced review requested due to automatic review settings October 20, 2026 01:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Shared-timer teardown, cross-thread shutdown, and borrowed-executor lifetimes warrant final human concurrency review.

No open issues 🎉

21 resolved since last review

And 1 more resolved.

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 20, 2026 02:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Shared-timer lifetime, borrowed executors, and concurrent shutdown guarantees warrant final human concurrency review.

No open issues 🎉

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 20, 2026 03:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

3 open issues

Review effort: Lite

Comment on lines 70 to +73
static Result<std::shared_ptr<RestCatalog>> Make(const RestCatalogProperties& config,
Executor* metrics_executor = nullptr,
ClientFactory client_factory = {});
ClientFactory client_factory = {},
Executor* auth_executor = nullptr,
Executor* metrics_executor = nullptr);
Comment thread src/iceberg/util/scheduled_executor.cc Outdated
Comment on lines +78 to +81
auto [it, inserted] = tasks_.emplace(
std::pair{deadline, id}, Task{.state = std::move(state),
.task = std::move(task),
.on_submit_failure = std::move(on_submit_failure)});
Comment on lines +88 to +98
std::optional<Task> cancelled;
{
std::lock_guard lock(mutex_);
auto it = by_id_.find(id);
if (it == by_id_.end()) return;
cancelled.emplace(std::move(it->second->second));
tasks_.erase(it->second);
by_id_.erase(it);
}
cv_.notify_one();
// Release callback captures outside the queue lock.
Copilot AI balanced review requested due to automatic review settings October 20, 2026 03:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +76 to +83
std::lock_guard lock(mutex_);
auto id = next_id_++;
auto [it, inserted] = tasks_.emplace(std::pair{deadline, id},
Task{.state = std::move(state),
.task = std::move(task),
.on_submission = std::move(on_submission)});
by_id_.emplace(id, it);
cv_.notify_one();
Comment on lines 70 to +73
static Result<std::shared_ptr<RestCatalog>> Make(const RestCatalogProperties& config,
Executor* metrics_executor = nullptr,
ClientFactory client_factory = {});
ClientFactory client_factory = {},
Executor* auth_executor = nullptr,
Executor* metrics_executor = nullptr);
Comment on lines +35 to +43
class InlineExecutor : public Executor {
public:
Status Submit(ExecutorTask task) override {
++submissions;
std::move(task)();
return {};
}
int submissions = 0;
};

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants