Skip to content

refactor: extract base HTTP resource from repetitive requests.Session wrappers #3390

@cbini

Description

@cbini

Problem

10 active ConfigurableResource classes independently implement the same requests.Session wrapper pattern, duplicating session lifecycle, URL construction, request wrapping, error handling, and auth setup. This makes it hard to add cross-cutting improvements (retries, rate limiting, metrics) and increases the cost of adding new API integrations.

Approach

Hook-based single-inheritance base class (BaseHTTPResource) in src/teamster/libraries/http/resources.py. Each subclass overrides only what it needs. The base provides built-in retry via tenacity, standardized error handling with rate-limit awareness, and pagination helpers for three common patterns.

Active resources (10)

Resource Auth Pagination Tier
SmartRecruitersResource X-SmartToken header None 1
PowerSchoolEnrollmentResource Basic auth page 1
OvergradResource ApiKey header offset 1
KnowBe4Resource Bearer header page 1
ZendeskResource HTTPBasicAuth cursor 2
FinalsiteResource JWT bearer cursor 2
CoupaResource OAuth2Session offset 2
GrowResource OAuth2 token fetch offset 2
AdpWorkforceNowResource OAuth2Session + mTLS offset 3
DeansListResource API key per school offset 3

Dead resources (4, preserved untouched)

AdpWorkforceManagerResource, MClassResource, DibelsDataSystemResource, CouchdropResource — no active consumers.

Base class design

Extension hooks

Hook Default behavior Override example
_setup_session() No-op (subclass sets auth + _base_url) Every subclass
_prepare_request(method, url, kwargs) Pass-through DeansList injects school_id
_handle_error(response, error) 429: sleep + retry; 401: re-auth + retry; 5xx: retry; other: raise Zendesk custom rate-limit headers
_get_retry_after(response) Parses Retry-After / X-RateLimit-Reset headers ADP WFN computed delay
_reauthenticate() Re-raises (no re-auth) OAuth2 token refresh flows

Built-in retry (tenacity)

  • stop_after_attempt(3)
  • wait_exponential_jitter(initial=1, max=60)
  • retry_if_exception_type(HTTPError)

Pagination helpers

All return Iterator[list[dict]] with fetch_page and extract_records callbacks.

  • _paginate_cursor — cursor-based (Zendesk, Finalsite)
  • _paginate_offset — offset/limit (Overgrad, Grow, Coupa, DeansList, ADP WFN)
  • _paginate_page — page number (KnowBe4, PowerSchool)

Migration tiers

Tier 1 — Direct drop-in (4 resources)

SmartRecruitersResource, PowerSchoolEnrollmentResource, OvergradResource, KnowBe4Resource

Override _setup_session() only, optionally _get_url().

Tier 2 — Additional hooks (4 resources)

ZendeskResource, FinalsiteResource, CoupaResource, GrowResource

Uses _get_retry_after override, OAuth2Session, or non-trivial _setup_session.

Tier 3 — Complex (2 resources)

AdpWorkforceNowResource, DeansListResource

OAuth2 + mTLS, _prepare_request override, custom Avro writing.

Testing

  • Base class unit tests — mocked request pipeline, retry, error handling, pagination helpers
  • Subclass mocked tests_setup_session, _get_url, override behavior per resource
  • Pagination contract tests — multi-page sequences with realistic response shapes, edge cases
  • Integration validationdagster definitions validate after each tier

Design spec

docs/superpowers/specs/2026-03-25-base-http-resource-design.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions