"""Integration coverage for parse timeout/failure publication semantics.""" from __future__ import annotations import asyncio from uuid import uuid4 import pytest from ragcore.domain.sources import SourceFingerprint from ragcore.infrastructure.parsers import TextParser from ragcore.ingestion.parsing import ( CanonicalArtifact, ParseRequest, ParserFailureError, ParserRouter, ParserTimeoutError, ParsingService, ) def request() -> ParseRequest: return ParseRequest( uuid4(), SourceFingerprint("b" * 64), b"hello", "text/plain", "a.txt" ) class Publisher: def __init__(self) -> None: self.published: list[CanonicalArtifact] = [] async def publish(self, artifact: CanonicalArtifact) -> None: self.published.append(artifact) class FailingParser: def supports(self, request: ParseRequest) -> bool: return True async def parse(self, request: ParseRequest) -> CanonicalArtifact: raise ValueError("fixture parser failure") class SlowParser(TextParser): async def parse(self, request: ParseRequest) -> CanonicalArtifact: await asyncio.sleep(0.05) return await super().parse(request) @pytest.mark.asyncio async def test_success_publishes_canonical_artifact_after_parse() -> None: publisher = Publisher() service = ParsingService(ParserRouter((TextParser(),)), publisher) artifact = await service.parse_and_publish(request()) assert publisher.published == [artifact] assert artifact.source_fingerprint.value == "b" * 64 @pytest.mark.asyncio async def test_parser_failure_and_timeout_leave_no_published_version() -> None: failed_publisher = Publisher() failing = ParsingService(ParserRouter((FailingParser(),)), failed_publisher) with pytest.raises(ParserFailureError): await failing.parse_and_publish(request()) timed_publisher = Publisher() timed = ParsingService( ParserRouter((SlowParser(),)), timed_publisher, timeout_seconds=0.001 ) with pytest.raises(ParserTimeoutError): await timed.parse_and_publish(request()) assert failed_publisher.published == [] assert timed_publisher.published == []