fix(ebook): enhance EPUB ingestion with error handling and incrmental commits
This commit is contained in:
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user