Aller au contenu principal

Middleware

Le pipeline de middleware permet d'intercepter et modifier les opérations d'indexation et de recherche. C'est le mécanisme d'extension principal pour les préoccupations transverses comme le logging, le cache, les métriques et la sécurité.

Concepts de base​

Un middleware est une classe qui implémente des hooks dans le cycle de vie :

from whoosh.middleware.base import Middleware
from whoosh.middleware.context import MiddlewareContext

class MonMiddleware(Middleware):
def before_search(self, context: MiddlewareContext) -> MiddlewareContext:
# Modifier context.query ou context.metadata
return context

def after_search(self, context: MiddlewareContext) -> MiddlewareContext:
# Accéder à context.results
return context

Hooks disponibles​

HookQuandUtilisations courantes
startup(context)InitialisationOuvrir connexions, remplir caches
shutdown(context)NettoyageFermer connexions, flush buffers
before_index(context)Avant indexationValidation, enrichissement, flags compression
after_index(context)Après indexationMétriques, événements, invalidation cache
before_delete(context)Avant suppressionJournalisation audit, contrôle d'accès
after_delete(context)Après suppressionMétriques, invalidation cache
before_search(context)Avant rechercheRéécriture de requête, cache, auth
after_search(context)Après résultatsLogging, métriques, modification résultats
on_error(context, exc)Sur exceptionGestion d'erreur, fallbacks
on_commit(context)Après commitMétriques, notifications

Classes intégrées​

MetricsMiddleware​

from whoosh.middleware import MetricsMiddleware

metrics = MetricsMiddleware()
# Après opérations:
stats = metrics.get_metrics()
# Retourne: {"documents_indexed": N, "searches_executed": N}

CacheMiddleware​

from whoosh.middleware import CacheMiddleware

cache = CacheMiddleware()
cached = cache.get_cached("requête utilisateur")
cache.set_cached("requête utilisateur", results)

MiddlewareChain​

from whoosh.middleware import MiddlewareChain

chain = MiddlewareChain([
MetricsMiddleware(),
CacheMiddleware()
])

# Exécuter un hook before
context = MiddlewareContext("search")
context.query = "test"
context = chain.run_before("before_search", context)

# ... opération core ...

# Exécuter un hook after
context = chain.run_after("after_search", context)

Intégration​

Avec Writer​

from whoosh.middleware.integration import apply_middleware_to_writer

writer = apply_middleware_to_writer(ix.writer(), chain.middlewares)

with writer:
writer.add_document(title="Bonjour", content="Monde")

Avec Searcher​

from whoosh.middleware.integration import apply_middleware_to_searcher

searcher = apply_middleware_to_searcher(ix.searcher(), chain.middlewares)
results = searcher.search("query")

Exemple: middleware personnalisé​

class RequestLoggingMiddleware(Middleware):
"""Journaliser toutes les recherches."""

def before_search(self, context: MiddlewareContext):
context.metadata["request_id"] = generate_request_id()
logger.info(f"Recherche: {context.query}")
return context

def after_search(self, context: MiddlewareContext):
logger.info(f"Trouvé: {len(context.results)} résultats")
return context

class RateLimitMiddleware(Middleware):
"""Abandonner les recherches dépassant la limite."""

def before_search(self, context: MiddlewareContext):
if not rate_limiter.allow(context):
raise StopOperation("Limite de taux dépassée")
return context

Gestion des erreurs​

class ResilientMiddleware(Middleware):
"""Continuer malgré les erreurs non critiques."""

def after_search(self, context: MiddlewareContext) -> MiddlewareContext:
try:
send_to_analytics(context.results)
except Exception:
logger.warning("Analytics failed", exc_info=True)
return context

Bonnes pratiques​

  1. Sans état: Utilisez context.metadata pour les données par requête
  2. Fail fast: Utilisez fail_open=True uniquement pour middleware non critique
  3. L'ordre compte: Placez le cache avant les métriques, l'auth avant le routage
  4. Performance: Gardez les hooks légers; utilisez async pour les I/O
  5. Testabilité: Mockez le contexte pour tester le middleware isolément

Middleware Moderne (Whoosh-NG 2.0)​

Whoosh-NG 2.0 ajoute un package middleware moderne (whoosh_modern.middleware) avec un middleware de résilience de type wrapper (réessaissance, cache, journalisation) et un middleware basé sur des hooks pour le stockage, la recherche et l'analyse. Pour plus de détails sur l'architecture moderne du middleware, l'intégration de plugins et le déploiement, consultez le Guide Middleware & Pipeline de Plugins.