Skip to content

Latest commit

 

History

History
277 lines (195 loc) · 5.07 KB

File metadata and controls

277 lines (195 loc) · 5.07 KB

HTTP Transport

This document describes the HTTP transport behavior introduced in version 0.8.0.

The public client remains synchronous. Ordinary usage does not need to configure sessions or retries.

Existing usage

Existing construction continues to work:

import mlbstatsapi

mlb = mlbstatsapi.Mlb()
player = mlb.get_person(664034)

The client remains synchronous. Async support is not part of version 0.8.0.

Context manager

Prefer a context manager when you want automatic cleanup of a library-created Session:

import mlbstatsapi

with mlbstatsapi.Mlb() as mlb:
    player = mlb.get_person(664034)

Exiting the block closes a Session created by the library.

It does not close a caller-owned injected Session.

Explicit cleanup

You can also close the client explicitly:

mlb = mlbstatsapi.Mlb()

try:
    player = mlb.get_person(664034)
finally:
    mlb.close()

Repeated close() calls are safe.

Default timeout

Every request uses an explicit timeout.

The default is:

DEFAULT_TIMEOUT = (3.05, 30.0)

That means:

3.05 seconds: connection timeout
30 seconds: read timeout

The read timeout is the maximum wait while reading response data. It is not one total wall-clock duration for the complete request.

Custom timeout

A scalar applies the same value to both connect and read phases:

mlb = mlbstatsapi.Mlb(timeout=10)

A tuple provides separate connect and read values:

mlb = mlbstatsapi.Mlb(
    timeout=(5.0, 60.0),
)

Shared Session model

One requests.Session is shared by the client's adapters:

Mlb client
├── v1 adapter ────┐
│                  ├── shared requests.Session
└── v1.1 adapter ──┘

A Session manages:

  • Reusable connection pools
  • Shared HTTP configuration
  • Mounted retry adapters on library-created Sessions

A Session is not:

  • A response cache
  • One guaranteed permanent TCP connection
  • An async transport

Session injection

Advanced callers may inject a Session:

import requests
import mlbstatsapi

session = requests.Session()

try:
    mlb = mlbstatsapi.Mlb(session=session)
    player = mlb.get_person(664034)
finally:
    session.close()

Ownership rules:

Library-created Session
    The library owns and closes it

Caller-injected Session
    The caller owns and closes it

The library does not install or replace retry adapters on caller-injected Sessions.

Callers who inject a Session control its retry, TLS, proxy, and adapter configuration.

Default retry policy

Library-created Sessions mount a bounded retry policy for GET requests.

Initial request: 1
Maximum retries: 3
Maximum total attempts: 4
Allowed method: GET
Backoff factor: 0.5
Retry-After respected: yes

Retryable HTTP statuses:

429
500
502
503
504

Non-retryable ordinary client statuses:

400
401
403
404

Additional rules:

  • Retries are bounded
  • Only GET requests are retried
  • Invalid JSON is not retried
  • Pydantic validation failures are not retried
  • Application parsing failures are not retried
  • A final 404 preserves existing not-found behavior
  • A final 429 preserves existing 4xx compatibility
  • A final 5xx raises MlbHttpError

Retries improve resilience for transient failures. They do not guarantee success.

Structured exceptions

TheMlbStatsApiException
├── MlbTransportError
│   └── MlbTimeoutError
├── MlbHttpError
└── MlbDecodeError

Imports:

from mlbstatsapi import (
    MlbDecodeError,
    MlbHttpError,
    MlbTimeoutError,
    MlbTransportError,
    TheMlbStatsApiException,
)

Precise handling:

try:
    player = mlb.get_person(664034)
except MlbTimeoutError:
    print("The MLB API timed out")
except MlbTransportError:
    print("The request could not reach the MLB API")
except MlbHttpError as exc:
    print(
        exc.status_code,
        exc.reason,
        exc.url,
    )
except MlbDecodeError:
    print("The MLB API returned invalid JSON")

Backward-compatible handling remains valid because all new errors inherit from TheMlbStatsApiException:

try:
    player = mlb.get_person(664034)
except TheMlbStatsApiException:
    print("The MLB request failed")

Notes:

  • MlbTimeoutError is a subtype of MlbTransportError
  • All new errors inherit from TheMlbStatsApiException
  • Existing broad exception handling remains valid
  • Original Requests or JSON decoding failures are preserved through exception chaining

HTTP exception attributes

MlbHttpError exposes:

status_code
reason
url

It does not expose a response body or Response object.

Existing 404 behavior

Version 0.8.0 preserves endpoint-specific not-found behavior.

Depending on the endpoint, a 404 may become:

None
[]
{}

Not every 404 raises MlbHttpError.

No response caching

Shared Sessions pool network connections. They do not cache MLB response bodies.

The client has no default response cache.

No async support

The client remains synchronous.

Async support is not part of version 0.8.0.