Source code for sphinx_typesense.indexer

"""Backward compatibility module for TypesenseIndexer.

This module maintains backward compatibility by re-exporting TypesenseBackend
as TypesenseIndexer and exposing the schema and weight constants.

.. deprecated::
    Use sphinx_typesense.backends.typesense.TypesenseBackend instead.

Example:
    New code should use::

        from sphinx_typesense.backends.typesense import TypesenseBackend

        backend = TypesenseBackend(app)
        count = backend.index_all()

    Legacy code using TypesenseIndexer continues to work::

        from sphinx_typesense.indexer import TypesenseIndexer

        indexer = TypesenseIndexer(app)
        count = indexer.index_all()

"""

from __future__ import annotations

from typing import TYPE_CHECKING

import typesense
import typesense.exceptions
from sphinx.util import logging
from typesense.exceptions import (
    HTTPStatus0Error,
    RequestUnauthorized,
    ServiceUnavailable,
    Timeout,
)

from sphinx_typesense.backends.typesense import (
    DOC_TYPE_PRIORITIES,
    DOC_TYPE_WEIGHTS,
    DOCS_SCHEMA,
    TypesenseBackend,
)

if TYPE_CHECKING:
    from sphinx.application import Sphinx

logger = logging.getLogger(__name__)

# Backward compatibility alias
TypesenseIndexer = TypesenseBackend

__all__ = [
    "DOCS_SCHEMA",
    "DOC_TYPE_PRIORITIES",
    "DOC_TYPE_WEIGHTS",
    "TypesenseBackend",
    "TypesenseIndexer",
    "index_documents",
]


def _log_indexing_error(exc: Exception) -> None:
    """Log an indexing error with appropriate context.

    Handles different exception types with specific, actionable messages
    to help users diagnose connection and configuration issues.

    Args:
        exc: The exception that occurred during indexing.

    """
    if isinstance(exc, RequestUnauthorized):
        logger.warning("sphinx-typesense: Authentication failed. Check typesense_api_key in conf.py")
    elif isinstance(exc, ServiceUnavailable):
        logger.warning("sphinx-typesense: Server unavailable. Documentation build completed without search indexing.")
    elif isinstance(exc, (Timeout, HTTPStatus0Error)):
        logger.warning("sphinx-typesense: Connection timed out. Check server availability and network configuration.")
    elif isinstance(exc, (ConnectionError, TimeoutError)):
        logger.warning(
            "sphinx-typesense: Network error (%s). Ensure Typesense server is running and accessible.",
            type(exc).__name__,
        )
    elif isinstance(exc, typesense.exceptions.TypesenseClientError):
        logger.warning("sphinx-typesense: Client error: %s", exc)
    elif isinstance(exc, OSError):
        logger.warning("sphinx-typesense: System error: %s", exc)
    else:
        logger.warning("sphinx-typesense: Unexpected error: %s", exc)


[docs] def index_documents(app: Sphinx, exception: Exception | None) -> None: """Sphinx event handler to index documents after build. This function is called by Sphinx after the build completes. It creates a TypesenseBackend and indexes all HTML files if no exception occurred. Implements graceful degradation: if Typesense is unavailable, the build completes successfully with a warning. Search will not be available until the server is restored and docs are rebuilt. Args: app: The Sphinx application instance. exception: Exception raised during build, if any. """ logger.debug("sphinx-typesense: index_documents event handler invoked") # Don't index if build failed if exception: logger.debug("sphinx-typesense: Skipping indexing due to build exception: %s", exception) return # Check if indexing is enabled if not app.config.typesense_enable_indexing: logger.debug("sphinx-typesense: Indexing is disabled via configuration") return # Check if API key is configured if not app.config.typesense_api_key: logger.warning("sphinx-typesense: Skipping indexing - no API key configured") return logger.debug("sphinx-typesense: Starting indexing process") try: backend = TypesenseBackend(app) count = backend.index_all() if count > 0: logger.info("sphinx-typesense: Successfully indexed %d documents", count) else: logger.debug("sphinx-typesense: No documents indexed") except ( RequestUnauthorized, ServiceUnavailable, Timeout, HTTPStatus0Error, ConnectionError, TimeoutError, typesense.exceptions.TypesenseClientError, OSError, ) as e: _log_indexing_error(e)
# Note: We intentionally don't re-raise - indexing failure shouldn't fail the build