Saved_Jobs_Persistence.md 2.3 KB

Phase 5 — Saved jobs persistence and revalidation

Status: Implemented
Date: 2026-10-12

Scope

  • Persist saved Indeed listings with SwiftData
  • Dedupe on save by indeedJobKey
  • Keep unavailable jobs visible with status; Open on Indeed still offered
  • Background revalidation (24h stale interval)
  • Settings: clear local saved jobs + JSON export

Architecture

Save toggle (Search / Saved)
  → SavedJobsStore (SwiftDataSavedJobsStore | MockSavedJobsStore)
  → SavedJobEntity (unique indeedJobKey + JobListing JSON snapshot)
  → UI refresh via ViewModel version bumps

Launch / Saved Jobs appear
  → SavedJobsRevalidator.runPass()
  → JobValidationService (source signal → optional HEAD)
  → updateListing(availability, lastVerifiedAt)

What shipped

Component Path
Model container Persistence/PersistenceController.swift
SwiftData entity Persistence/SavedJobEntity.swift
Persisted store Persistence/SwiftDataSavedJobsStore.swift
Revalidator Persistence/SavedJobsRevalidator.swift
Protocol SavedJobsStore (+ updateListing, clearAll)
Live DI AppDependencies.live → SwiftData + HTTP HEAD for saved revalidation
Preview DI AppDependencies.preview → MockSavedJobsStore
Settings Clear local data + export JSON
Tests indeed_ai_job_searchTests/SavedJobsPersistenceTests.swift

Policies

Policy Value
Dedupe key indeedJobKey (unique SwiftData attribute)
Snapshot Full JobListing JSON in entity
Revalidation interval 24 hours (SavedJobsRevalidator.defaultStaleInterval)
Unavailable rows Kept; muted/strikethrough via existing JobRowView
Search validation Unchanged — source signals only (no HEAD during search)
Saved revalidation Source signal + HTTPJobValidationService HEAD when unknown

Acceptance checklist

  • Save/unsave survives relaunch (SwiftData disk store)
  • Dedupe on save by indeedJobKey
  • Unavailable jobs remain visible with status; Open on Indeed still available
  • Stale saved jobs revalidated on launch / Saved Jobs navigation
  • Settings clear local data + export JSON
  • Unit tests for store + revalidator

Out of scope (Phase 6+)

  • Persisted job alerts / notification history
  • Cloud sync / iCloud