sendBlocking blijft hangen tot het time-out

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 op RetailerPaymentResponse vangt 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.