Skip to content

feat: upgrade to Okta SDK v3 and pool the client on the server loop#509

Draft
somethingnew2-0 wants to merge 2 commits into
mainfrom
pcollins/epic-dirac-d5ca0e
Draft

feat: upgrade to Okta SDK v3 and pool the client on the server loop#509
somethingnew2-0 wants to merge 2 commits into
mainfrom
pcollins/epic-dirac-d5ca0e

Conversation

@somethingnew2-0

@somethingnew2-0 somethingnew2-0 commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Implements POST_MIGRATION_TODO 11a (Okta SDK v3 upgrade) and 11b (shared pooled Okta client). Both are contained behind the OktaService facade, so no call site outside the service changed — the syncer, operations, integrity checks, and CLI all keep going through the same facade methods.

11a — okta 2.9.8 → 3.4.4

v3 is the openapi-generator rewrite the TODO anticipated (okta.api.*, Pydantic models). Two realities cut the blast radius down from what that note assumed, and are the key things to know when reviewing:

  • The tuple contract survived. Despite the rewrite, the generated methods still return (data, resp, error) / (resp, error) and return API errors rather than raising them. So the facade's tuple-based retry loop stayed intact — the main change is response.get_status()response.status_code and reading the rate-limit reset header case-insensitively.
  • Group ownership is now native. v3 ships assign_group_owner / delete_group_owner / list_group_owners, so the hand-rolled request-executor plumbing the TODO called out is gone.

Other v3 deltas absorbed inside the facade: method renames (add_group / replace_group / assign_user_to_group / unassign_user_from_group); cursor-based pagination via PaginationHelper (the old resp.next() walker is gone, and the SDK's bundled paginate_all helper is unusable in this build — it calls *_with_http_info variants that don't exist — so the facade drives the after cursor itself); Group.profile as an anyOf union reached through actual_instance; and already-parsed datetime fields (no more dateutil parsing). get_user_schema recovers the schema _links href from the raw response body because the v3 UserType model drops _links.

Retry posture: rate-limiting and timeouts are both the SDK's job. It retries 429s (honoring X-Rate-Limit-Reset) up to rateLimit.maxRetries (default 2), and requestTimeout bounds each request — an aiohttp per-request socket timeout plus a cumulative deadline across those retries. The facade keeps no retry loop or wait_for of its own; a thin _call wrapper just maps the SDK's "gave up" outcomes — a request timeout, or a 429 that outlived its retries — to OktaTimeout, which the membership/ownership fan-out catches and swallows (the syncer reconciles later). 5xx errors are intentionally not retried — left to Okta.

11b — pooled client

OktaService now holds one client (and its pooled aiohttp connector) for the server loop, created in the FastAPI lifespan and reused by _okta_client() when asyncio.get_running_loop() matches the loop it was built on. CLI invocations and per-test loops still build a fresh client per call — no pooled client is started when Okta is unconfigured, and the running-loop check prevents cross-loop session reuse. The TODO's "measure before bothering" caveat still stands; this just puts the pooling in place to measure.

Verification note

The test suite mocks Okta at the facade boundary, so the v3 wire behavior it can't exercise — 429/rate-limit handling, multi-page pagination, get_user_schema's _links recovery, and the group-owner endpoints (off by default behind OKTA_USE_GROUP_OWNERS_API) — should be validated against a live/staging org before this rolls out, as the TODO flagged.

@somethingnew2-0 somethingnew2-0 force-pushed the pcollins/epic-dirac-d5ca0e branch from acad342 to 78505f4 Compare July 7, 2026 21:22
@somethingnew2-0 somethingnew2-0 changed the base branch from main to pcollins/charming-villani-7c28be July 7, 2026 21:22
@somethingnew2-0 somethingnew2-0 force-pushed the pcollins/epic-dirac-d5ca0e branch 2 times, most recently from 29db6f8 to 2668815 Compare July 7, 2026 21:39
@somethingnew2-0 somethingnew2-0 force-pushed the pcollins/charming-villani-7c28be branch from b1c3d04 to 89cfcee Compare July 8, 2026 16:59
Base automatically changed from pcollins/charming-villani-7c28be to main July 8, 2026 17:17
Implements POST_MIGRATION_TODO items 11a (Okta SDK v3 upgrade) and 11b
(shared pooled Okta client), both contained behind the OktaService facade.

11a bumps okta 2.9.8 -> 3.4.4 (the openapi-generator rewrite). The
generated methods keep the (data, resp, error) tuple contract and return
errors rather than raising, so the tuple-based retry loop survives (just
response.get_status() -> response.status_code). Group ownership is now a
native SDK feature, replacing the hand-rolled request-executor plumbing.
Also handles method renames, cursor-based pagination, the GroupProfile
anyOf union, and already-parsed datetime fields. The SDK's built-in
rate-limit retry is disabled so _retry stays the single backoff layer.

11b holds one client (and its pooled aiohttp connector) for the server
loop via a lifespan hook, reused when the running loop matches; CLI and
per-test loops keep a fresh client per call.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@somethingnew2-0 somethingnew2-0 force-pushed the pcollins/epic-dirac-d5ca0e branch from 2668815 to caa4f6f Compare July 14, 2026 01:49
…ustom _retry

The v3 SDK retries rate-limited (429) requests internally, honoring the
X-Rate-Limit-Reset header, and its requestTimeout config bounds each request
(an aiohttp per-request socket timeout plus a cumulative deadline across those
retries). So the facade's hand-rolled _retry loop and asyncio.wait_for ceiling
are both redundant.

Remove them and rely on the SDK: its built-in 429 retries (default
maxRetries=2) and requestTimeout. A thin _call wrapper inspects the returned
error and raises OktaTimeout when the SDK gave up — a request timeout or a 429
that outlived its retries (OktaAPIError status 429) — so the
membership/ownership fan-out can still catch and swallow it and let the syncer
reconcile. 5xx errors are intentionally no longer retried; other errors pass
through unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@somethingnew2-0 somethingnew2-0 force-pushed the pcollins/epic-dirac-d5ca0e branch from e9cb385 to 7e001a0 Compare July 14, 2026 02:52
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.

1 participant