Skip to content

Refactor: FetchResult / ContentSource as tagged unions #20

@VGonPa

Description

@VGonPa

Deferred refactor from WS2 Phase 2. Not user-visible — internal type hygiene.

Today, `FetchResult` and `ContentSource` are dataclasses where success-only fields (`text`, `extracted_at`, …) and failure-only fields (`http_status`, `failure_reason`, `attempts`, …) coexist as Optionals. Nothing in the type system prevents a malformed state where both are populated or both are absent. Callers must check sentinel fields to know which case they have.

Goal

Make success and failure mutually exclusive variants by construction: tagged unions / discriminated types (e.g. `FetchSuccess` + `FetchFailure` under a `FetchResult = FetchSuccess | FetchFailure` alias), with pydantic / pattern matching enforcement.

Acceptance

  • `mypy --strict` rules out illegal states.
  • Callers switch on the variant (pattern match or `isinstance`); no more `if result.text is not None` smell.
  • JSON serialization / deserialization preserves the variant (`type: "success" | "failure"` discriminator on the wire).
  • All existing tests pass without behavior change.

Risk

Touches the persistence layer (`items.json` schema). Needs a one-shot migration of existing `ContentSource` payloads — handled by reading the legacy shape and writing the new shape on next save. Snapshot (#C) becomes very useful here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions