Mise en cache des schemas
apicurio-serdes met en cache les schemas après la première récupération afin que les appels de sérialisation
suivants n'effectuent pas de requêtes HTTP. Cette page explique le fonctionnement de la mise en cache des schemas et
ce qu'il faut en attendre.
Fonctionnement du cache
Lorsque vous appelez un serializer pour la première fois, il demande à l'ApicurioRegistryClient de récupérer le
schema depuis le registry. Le client stocke le résultat sous forme de CachedSchema — une dataclass gelée (immutable)
— dans un cache en mémoire indexé par (group_id, artifact_id). Le gel de l'entrée en cache empêche la mutation
accidentelle des données de schema partagées.
First call:
serializer(data, ctx)
│
▼
ApicurioRegistryClient.get_schema("UserEvent")
│
├── Cache miss → HTTP GET /groups/.../artifacts/UserEvent/versions/latest/content
│ └── Store result in cache
│
└── Return CachedSchema (schema dict + globalId + contentId)
Subsequent calls:
serializer(data, ctx)
│
▼
ApicurioRegistryClient.get_schema("UserEvent")
│
└── Cache hit → Return immediately (no HTTP request)
Durée de vie du cache
Le cache persiste pendant toute la durée de vie de l'instance ApicurioRegistryClient. Par défaut, il n'y a pas de
TTL (time-to-live) ni d'expiration — une fois qu'un schema est mis en cache, il y reste jusqu'à ce que le client soit
collecté par le ramasse-miettes ou que l'entrée soit évincée par la politique LRU.
Les lookups basés sur l'artifact (get_schema, register_schema) peuvent recevoir un TTL configurable via
cache_ttl_seconds. Une fois le TTL écoulé, le prochain appel récupère à nouveau depuis le registry et intègre
automatiquement toute nouvelle version de schema.
Les lookups basés sur l'identifiant (get_schema_by_global_id, get_schema_by_content_id) sont adressés par contenu
et immuables — un globalId ou contentId fait toujours référence au même contenu de schema. Ces entrées n'expirent
jamais, quelle que soit la valeur de cache_ttl_seconds.
Cela signifie :
- Au sein d'un processus de longue durée (par ex., une boucle de consommation Kafka), les schemas sont récupérés une seule fois au démarrage et jamais ensuite (sauf si un TTL est configuré ou si des entrées sont évincées par la politique LRU).
- Si un schema change dans le registry et qu'aucun TTL n'est configuré, le client en cours d'exécution ne verra
pas la nouvelle version avant un redémarrage. Avec
cache_ttl_secondsconfiguré, le client intègre les nouvelles versions automatiquement après chaque fenêtre TTL.
# Schema cached for the lifetime of this client
client = ApicurioRegistryClient(
url="http://registry:8080/apis/registry/v3",
group_id="com.example.schemas",
)
# All serializers sharing this client share the same cache
serializer_a = AvroSerializer(registry_client=client, artifact_id="UserEvent")
serializer_b = AvroSerializer(registry_client=client, artifact_id="OrderEvent")
# Only 2 HTTP requests total, regardless of how many messages are serialized
for event in events:
serializer_a(event, ctx)
Éviction du cache et limites de taille
Deux paramètres de constructeur contrôlent le comportement du cache :
cache_max_size(défaut1000) : nombre maximum d'entrées dans chaque cache. Lorsque la limite est atteinte, l'entrée la moins récemment utilisée est évincée pour faire de la place aux nouvelles entrées (politique LRU). S'applique au cache de schemas et au cache d'identifiants.cache_ttl_seconds(défautNone) : TTL optionnel en secondes pour les entrées du cache de schemas basé sur l'artifact. Après cette durée, l'entrée est traitée comme un cache miss et le registry est de nouveau interrogé. Les entrées du cache d'identifiants n'expirent jamais.
from apicurio_serdes import ApicurioRegistryClient
# Limiter les deux caches à 500 entrées et récupérer les schemas d'artifact toutes les 5 minutes
client = ApicurioRegistryClient(
url="http://registry:8080/apis/registry/v3",
group_id="com.example.schemas",
cache_max_size=500,
cache_ttl_seconds=300,
)
Ces deux paramètres lèvent une ValueError en cas de valeur invalide : cache_max_size doit être au moins 1 ;
cache_ttl_seconds doit être None ou strictement positif.
Partage du cache
Plusieurs serializers qui partagent la même instance d'ApicurioRegistryClient partagent également le cache.
Si deux serializers utilisent le même artifact_id, le schema n'est récupéré qu'une seule fois :
# Same client → same cache → one HTTP request for "UserEvent"
ser1 = AvroSerializer(registry_client=client, artifact_id="UserEvent")
ser2 = AvroSerializer(registry_client=client, artifact_id="UserEvent")
Si vous créez des instances distinctes d'ApicurioRegistryClient, chacune possède son propre cache indépendant.
Thread Safety
Le cache est protégé par un verrou réentrant (threading.RLock). Plusieurs threads peuvent appeler get_schema
de manière concurrente en toute sécurité :
- Si deux threads demandent le même schema simultanément, un seul effectue la requête HTTP ; l'autre attend sur le verrou puis lit depuis le cache.
- Les opérations de lecture sur un schema déjà en cache n'acquièrent pas le verrou (chemin rapide).
Cela signifie que vous pouvez partager en toute sécurité une seule instance d'ApicurioRegistryClient et ses
serializers entre plusieurs threads dans un producteur multi-thread.
Quand créer un nouveau client
Créez une nouvelle instance d'ApicurioRegistryClient lorsque :
- Le schema a été mis à jour dans le registry et vous avez besoin de la nouvelle version, et qu'aucun
cache_ttl_secondsn'est configuré. Aveccache_ttl_secondsconfiguré, le client intègre les nouvelles versions de schemas automatiquement après chaque fenêtre TTL. - Vous vous connectez à un registry différent ou changez de groupe.
- Vous souhaitez réinitialiser le cache (par ex., dans les tests).
Dans la plupart des scénarios de production, une seule instance de client par application est suffisante.