Symptoom
Je schakelde een operatie over naar blocking-modus met BlockingMessageGateway, en nu wordt de coroutine nooit hervat bij een fout — hij blijft hangen tot er een TimeoutCancellationException wordt gegooid. Succesvolle operaties werken prima; alleen fouten blijven hangen. Een login of betaling die een fout zou moeten teruggeven, loopt in plaats daarvan gewoon vast door de time-out.
Oorzaak
sendBlocking wordt hervat wanneer een bericht van het exacte type waar je op wacht arriveert. Als je wacht op de succes-subtype (bijv. SuccessRetailerLoginResponse) en de operatie faalt, dan komt de fout binnen als een ander type (ErrorRetailerLoginResponse) — wat nooit overeenkomt met waar je op wacht. De gateway blijft wachten, en je coroutine blijft hangen tot de time-out afgaat.
De foutrespons werd geleverd. Je luisterde alleen niet naar het juiste type.
Oplossing
Wacht op het sealed supertype, niet op een subtype, en vertak daarna met when:
// FOUT — hervat alleen bij succes; elke fout leidt tot time-out
val r: SuccessRetailerLoginResponse = gateway.sendBlocking { clientSDK.sendLoginRequest() }
// GOED — hervat bij succes OF fout
val r: RetailerLoginResponse = gateway.sendBlocking(timeoutMillis = 30000) {
clientSDK.sendLoginRequest()
}
when (r) {
is SuccessRetailerLoginResponse -> { /* ok */ }
is ErrorRetailerLoginResponse -> { /* verwerk de fout */ }
}
Dezelfde regel geldt voor elke operatie: wacht op RetailerPaymentResponse, RetailerReversalResponse, enzovoort — het supertype — en vertak daarna. Het supertype dekt alle uitkomsten, dus zowel succes als fout hervatten je coroutine.
Onthoud dat betaling een derde uitkomst heeft,
PartialRetailerPaymentResponse. Wachten opRetailerPaymentResponsevangt deze op; alleen wachten op het succes-subtype zou zowel de fout- als de gedeeltelijke gevallen missen.
Blijft het time-out na het corrigeren van het type?
Als je op het supertype wacht en het toch time-out gaat, komt er echt geen respons aan — controleer of de gateway elk bericht ontvangt (gateway.onNewMessage(message) in je interceptor), dat je een actieve sessie hebt (zie Sessie- en loginlevenscyclus), en dat de time-out lang genoeg is voor de operatie. Verwerk altijd TimeoutCancellationException — een echte time-out is zelf een conditie waarop je app moet reageren.
Gerelateerd
- Hoe het berichtmodel werkt — de volledige uitleg van het supertype-patroon.
- Sessie- en loginlevenscyclus — een ontbrekende sessie levert ook geen respons op.