fix(ebook): enhance EPUB ingestion with error handling and incrmental commits

This commit is contained in:
2026-07-24 11:38:50 -04:00
parent 9ba8200673
commit fbb1ebfd56
+55 -50
View File
@@ -91,60 +91,65 @@ def ingest_configured_paths(session: Session, config: EbookSearchConfig) -> int:
def ingest_file(session: Session, path: Path, config: EbookSearchConfig) -> bool: def ingest_file(session: Session, path: Path, config: EbookSearchConfig) -> bool:
"""Ingest one EPUB file. Return True when the database changed.""" """Ingest one EPUB file. Return True when the database changed."""
resolved_path = path.expanduser().resolve() try:
logger.info("ebook_ingest_file_start path=%s", resolved_path) resolved_path = path.expanduser().resolve()
file_hash = sha256_file(resolved_path) logger.info("ebook_ingest_file_start path=%s", resolved_path)
existing = find_existing_source(session, resolved_path, file_hash) file_hash = sha256_file(resolved_path)
if existing is not None and existing.file_sha256 == file_hash: existing = find_existing_source(session, resolved_path, file_hash)
if existing is not None and existing.file_sha256 == file_hash:
stat = resolved_path.stat()
existing.file_path = str(resolved_path)
existing.file_mtime = datetime.fromtimestamp(stat.st_mtime, tz=UTC)
existing.file_size = stat.st_size
session.flush()
logger.info("ebook_ingest_file_unchanged source_id=%s path=%s", existing.id, resolved_path)
return False
if existing is not None:
logger.info("ebook_ingest_file_replacing source_id=%s path=%s", existing.id, resolved_path)
session.delete(existing)
session.flush()
stat = resolved_path.stat() stat = resolved_path.stat()
existing.file_path = str(resolved_path) parsed = parse_epub(resolved_path)
existing.file_mtime = datetime.fromtimestamp(stat.st_mtime, tz=UTC) source = EbookSource(
existing.file_size = stat.st_size title=parsed.title,
session.flush() author=parsed.author,
logger.info("ebook_ingest_file_unchanged source_id=%s path=%s", existing.id, resolved_path) language=parsed.language,
return False publisher=parsed.publisher,
if existing is not None: identifier=parsed.identifier,
logger.info("ebook_ingest_file_replacing source_id=%s path=%s", existing.id, resolved_path) file_path=str(resolved_path),
session.delete(existing) file_sha256=file_hash,
session.flush() file_mtime=datetime.fromtimestamp(stat.st_mtime, tz=UTC),
file_size=stat.st_size,
stat = resolved_path.stat()
parsed = parse_epub(resolved_path)
source = EbookSource(
title=parsed.title,
author=parsed.author,
language=parsed.language,
publisher=parsed.publisher,
identifier=parsed.identifier,
file_path=str(resolved_path),
file_sha256=file_hash,
file_mtime=datetime.fromtimestamp(stat.st_mtime, tz=UTC),
file_size=stat.st_size,
)
session.add(source)
session.flush()
chunk_index = 0
for spine_index, parsed_chapter in enumerate(parsed.chapters):
chapter = EbookChapter(
source_id=source.id,
spine_index=spine_index,
title=parsed_chapter.title,
href=parsed_chapter.href,
) )
session.add(chapter) session.add(source)
session.flush() session.flush()
chunk_index = add_chapter_chunks(session, source, chapter, parsed_chapter, chunk_index, config)
session.flush() chunk_index = 0
logger.info( for spine_index, parsed_chapter in enumerate(parsed.chapters):
"ebook_ingest_file_complete source_id=%s path=%s chapters=%s chunks=%s", chapter = EbookChapter(
source.id, source_id=source.id,
resolved_path, spine_index=spine_index,
len(parsed.chapters), title=parsed_chapter.title,
chunk_index, href=parsed_chapter.href,
) )
return True session.add(chapter)
session.flush()
chunk_index = add_chapter_chunks(session, source, chapter, parsed_chapter, chunk_index, config)
session.commit()
logger.info(
"ebook_ingest_file_complete source_id=%s path=%s chapters=%s chunks=%s",
source.id,
resolved_path,
len(parsed.chapters),
chunk_index,
)
except Exception:
logger.exception(f"ebook_ingest_file_error path={path}")
return False
else:
return True
def find_existing_source(session: Session, path: Path, file_hash: str) -> EbookSource | None: def find_existing_source(session: Session, path: Path, file_hash: str) -> EbookSource | None: