Skip to content

[optimization] Proactive refresh daemon #157

Description

  • Goal: keep the ~4-round-trip refresh latency off the hot path during an actively-querying
    session by refreshing both tokens in the background ahead of the CP token's ~5-min expiry. This is
    a pure latency optimization — correctness already lives in child 3's on-request refresh — so it
    lands after a functional PoC, not as a table-stakes hurdle before one.
  • Scope (in):
    • a background daemon thread that sleeps on a threading.Event until cp_expires_at − window
      (the CP token is the shorter clock), wakes, and runs _refresh() through the same single-flight
      gate as the on-request path; the Event lets close() interrupt it promptly.
    • the holder-side lifecycle the daemon necessitates: refcount of open OAuth Connections,
      park-don't-evict at refcount 0 (stop the daemon, keep the tokens — reversible), a short
      cancel-on-acquire linger to absorb dbt churn, Connection.close()holder.release()
      gaining teeth, and daemon=True as the never-hang backstop.
  • Out of scope: the on-request refresh (child 3, still the correctness floor — the daemon only
    pre-empts its latency); proactive re-login ahead of the 8h wall (child 8, which rides this daemon).
  • Depends on: children CCloudOAuth provider: login + on-request refresh + two auth views #153, Process-wide holder: one OAuth identity per process #154.
  • Prior art: ide-sidecarRefreshCCloudTokensBean (@Scheduled refreshTokens() every 60s,
    ConcurrentExecution.SKIP) with the proactive decision shouldAttemptTokenRefresh() (refresh iff
    a token expires before the next tick). mcp-confluentAuthContext.startRefreshLoop() /
    scheduleNextRefresh() (setTimeout at controlPlaneExpiresAt − window). Neither borrows the
    refcount / park-don't-evict / linger lifecycle
    — both simply refresh for the whole process /
    connection lifetime; that lifecycle is our own, driven by dbt's open-close-reopen churn.
  • Sized right: one thread + the refcount/park lifecycle + concurrency tests, layered on an
    already-shipped, already-correct provider + holder.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions