Confirmations immédiates et retardées
Dans cet article, vous allez découvrir les différences entre les confirmations immédiates et les confirmations retardées.
Confirmation immédiate
Pour de nombreuses applications, nous souhaitons garantir la confirmation immédiate des événements. Ainsi, la version conservée n’est pas en retard par rapport à la version actuelle en mémoire, et nous ne risquons pas de perdre le dernier état en cas de défaillance du grain. Nous pouvons le garantir en suivant les règles suivantes :
- Confirmez tous les appels de RaiseEvent à l’aide de ConfirmEvents avant le retour de la méthode de grain.
- Vérifiez que les tâches retournées par RaiseConditionalEvent se sont effectuées avant le retour de la méthode de grain.
- Évitez les attributs ReentrantAttribute ou AlwaysInterleaveAttribute pour ne traiter qu’un seul appel de grain à la fois.
Si nous suivons ces règles, cela signifie qu’une fois qu’un événement est déclenché, aucun autre code de grain ne peut s’exécuter tant que l’événement n’a pas été écrit dans le stockage. Ainsi, il est impossible d’observer des incohérences entre la version en mémoire et la version dans le stockage. Bien que cela soit souvent exactement ce que nous recherchons, cette situation présente également certains inconvénients potentiels.
Inconvénients potentiels
Si la connexion à un cluster ou un stockage distant est temporairement interrompue, le grain cesse d’être disponible. En fait, le grain ne peut exécuter aucun code tant qu’il est bloqué en attente de confirmation des événements, ce qui peut prendre un temps indéfini (le protocole de cohérence des journaux effectue de nouvelles tentatives jusqu’à ce que la connectivité du stockage soit restaurée).
Quand un grand nombre de mises à jour doivent être gérées pour une seule instance de grain, leur confirmation une par une peut s’avérer très inefficace, et entraîner par exemple un débit médiocre.
Confirmation retardée
Pour améliorer la disponibilité et le débit dans les situations mentionnées ci-dessus, les grains peuvent choisir d’effectuer l’une ou l’autre des opérations suivantes, ou les deux :
- Autoriser les méthodes de grain à déclencher des événements sans attendre de confirmation.
- Autoriser la réentrance pour que le grain puisse continuer à traiter les nouveaux appels, même si les appels précédents restent bloqués en attente de confirmation.
Cela signifie que le code de grain peut s’exécuter alors que certains événements sont toujours en attente de confirmation. L’API JournaledGrain<TGrainState,TEventBase> comporte des dispositions spécifiques qui permettent aux développeurs de contrôler précisément la gestion des événements non confirmés en cours.
Vous pouvez examiner la propriété suivante pour déterminer quels sont les événements non confirmés :
IEnumerable<EventType> UnconfirmedEvents { get; }
De plus, dans la mesure où l’état retourné par la propriété JournaledGrain<TGrainState,TEventBase>.State n’inclut pas l’effet des événements non confirmés, il existe une autre propriété
StateType TentativeState { get; }
Qui retourne un état « provisoire », obtenu à partir de « State » via l’application de tous les événements non confirmés. L’état provisoire est essentiellement la « meilleure supposition » de ce qui deviendra probablement le prochain état confirmé, une fois que tous les événements non confirmés auront été confirmés. Toutefois, rien ne garantit que cela sera le cas. En effet, le grain peut échouer ou, quand les événements perdent la compétition qui se joue entre eux, ils peuvent être annulés (s’ils sont conditionnels) ou apparaître à une position plus tardive que prévue dans la séquence (s’ils sont inconditionnels).
Garanties de concurrence
Notez que les garanties de planification au tour par tour (concurrence coopérative) d’Orleans s’appliquent toujours, même en cas d’utilisation de la réentrance ou de la confirmation différée. Cela signifie que même si plusieurs méthodes peuvent être en cours, une seule peut s’exécuter de manière active. Toutes les autres sont bloquées à l’état d’attente. Ainsi, il n’existe pas de réelles compétitions causées par des threads parallèles.
Notez en particulier que :
- Les propriétés State, TentativeState, Version et UnconfirmedEvents peuvent changer durant l’exécution d’une méthode.
- Mais de tels changements ne peuvent se produire qu’en cas de blocage à l’état d’attente.
Ces garanties supposent que le code utilisateur respecte les pratiques recommandées en ce qui concerne les tâches et les tâches asynchrones/en attente. Plus précisément, il n’utilise pas de tâches de pool de threads, ou alors uniquement pour du code qui n’appelle pas de fonctionnalités de grain et qui est correctement attendu.