FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring, source collection, LLM-based change analysis, enrichment, and account security (Turnstile, escalating lockout, email verification).
34 lines
1.1 KiB
Python
34 lines
1.1 KiB
Python
"""Layer 2: structured field comparison.
|
|
|
|
Compares the *set* of items (job postings, press releases, filings,
|
|
products - whatever the source's documents represent) between two
|
|
snapshots' `structured_summary["urls"]`/`["titles"]`. This is what catches
|
|
"a new job posting appeared" or "a press release was removed" without
|
|
needing a bespoke parser per source type - collection_service already
|
|
records the full current item set on every run, so this is a plain set
|
|
diff between two runs.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class StructuredDiff:
|
|
added: list[str] = field(default_factory=list)
|
|
removed: list[str] = field(default_factory=list)
|
|
|
|
@property
|
|
def has_changes(self) -> bool:
|
|
return bool(self.added or self.removed)
|
|
|
|
|
|
def diff_item_sets(previous_urls: list[str], current_urls: list[str]) -> StructuredDiff:
|
|
previous_set = set(previous_urls)
|
|
current_set = set(current_urls)
|
|
return StructuredDiff(
|
|
added=sorted(current_set - previous_set),
|
|
removed=sorted(previous_set - current_set),
|
|
)
|