Kotlin Academy · Les

Veerkrachtige coroutinearchitecturen ontwerpen

Combineer supervisorScope, retrylogica en handlers voor concurrency op productieniveau.

Les 4 van 413 stappen

Veerkrachtige coroutinearchitecturen ontwerpen is een gratis Kotlin Academy-les op CoddyKit. Dit is les 4 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Kotlin Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Kotlin Academy bevat in totaal 4 lessen.

Wat maakt coroutines veerkrachtig?

Veerkrachtige coroutinearchitecturen verwerken fouten op beheerste wijze: ze isoleren fouten, proberen tijdelijke fouten opnieuw, annuleren verouderd werk en ruimen bronnen deterministisch op.

import kotlinx.coroutines.*
// Resilience pillars:
// 1. Failure isolation (SupervisorJob)
// 2. Retry with backoff (retry operator / loop)
// 3. Timeout guards (withTimeout)
// 4. Clean teardown (finally + NonCancellable)
// 5. Observability (CoroutineExceptionHandler)
fun main() = runBlocking { println("Design for failure from the start") }

Patroon voor een bereik op appniveau

Maak één CoroutineScope op appniveau met SupervisorJob + handler. Injecteer dit in diensten, zodat ze allemaal dezelfde levenscyclus delen.

import kotlinx.coroutines.*
object AppCoroutineScope {
    private val handler = CoroutineExceptionHandler { _, e ->
        println("[AppScope] Uncaught: ${e.message}")
    }
    val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default + handler)
    fun cancel() = scope.cancel()
}

Opnieuw proberen met exponentiële wachttijd

Wikkel netwerkaanroepen in een lus voor nieuwe pogingen met exponentiële wachttijden om tijdelijke fouten beheerst af te handelen.

import kotlinx.coroutines.*
suspend fun <T> retryWithBackoff(
    times: Int = 3,
    initialDelay: Long = 100,
    block: suspend () -> T
): T {
    var delay = initialDelay
    repeat(times - 1) { attempt ->
        try { return block() }
        catch (e: Exception) {
            if (e is CancellationException) throw e
            println("Attempt ${attempt+1} failed, retrying in ${delay}ms")
            delay(delay)
            delay *= 2
        }
    }
    return block()
}
fun main() = runBlocking {
    var n = 0
    val result = retryWithBackoff {
        if (n++ < 2) throw RuntimeException("transient")
        "success"
    }
    println(result)
}

Patroon voor een circuitonderbreker

Een circuitonderbreker stopt met het aanroepen van een falende dienst na N fouten en wordt na een afkoelperiode opnieuw geopend — zo voorkom je kettingfouten.

import kotlinx.coroutines.*
class CircuitBreaker(val maxFailures: Int, val cooldownMs: Long) {
    private var failures = 0
    private var openUntil = 0L
    suspend fun <T> call(block: suspend () -> T): T {
        if (System.currentTimeMillis() < openUntil) throw RuntimeException("Circuit open")
        return try {
            val result = block()
            failures = 0
            result
        } catch (e: Exception) {
            if (e is CancellationException) throw e
            if (++failures >= maxFailures) openUntil = System.currentTimeMillis() + cooldownMs
            throw e
        }
    }
}

Time-out bij elke externe aanroep

Omgeef externe I/O altijd met withTimeout of withTimeoutOrNull. Laat een vastgelopen verbinding nooit onbeperkt een coroutine blokkeren.

import kotlinx.coroutines.*
suspend fun fetchWithTimeout(url: String): String? = withTimeoutOrNull(3000) {
    // ktor: client.get(url).body()
    delay(100) // simulate
    "response from $url"
}
fun main() = runBlocking {
    val result = fetchWithTimeout("https://api.example.com")
    println(result ?: "Timed out")
}

Gestructureerd bereik per functie

Maak per functie of scherm een afzonderlijk CoroutineScope met een eigen SupervisorJob. Annuleer het wanneer de functie wordt vernietigd.

import kotlinx.coroutines.*
class FeatureController {
    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
    fun start() {
        scope.launch { /* load data */ }
        scope.launch { /* subscribe to updates */ }
    }
    fun destroy() = scope.cancel()  // cancels all feature coroutines
}

Bronveiligheid met use()

Gebruik use { } voor AutoCloseable-bronnen. Combineer dit met annulering van coroutines: bronnen worden ook gesloten wanneer de coroutine wordt geannuleerd.

import kotlinx.coroutines.*
class Connection : AutoCloseable {
    override fun close() = println("Connection closed")
    suspend fun fetch(): String { delay(100); return "data" }
}
fun main() = runBlocking {
    val job = launch {
        Connection().use { conn ->
            println(conn.fetch())
        } // close() called even on cancellation
    }
    delay(50)
    job.cancelAndJoin()
}

Gecontroleerd afsluiten

Implementeer gecontroleerd afsluiten: accepteer geen nieuw werk meer, wacht tot actieve coroutines zijn voltooid en annuleer daarna het bereik.

import kotlinx.coroutines.*
class WorkQueue {
    private val scope = CoroutineScope(SupervisorJob())
    private val jobs = mutableListOf<Job>()
    fun submit(block: suspend () -> Unit) {
        jobs += scope.launch { block() }
    }
    suspend fun shutdown() {
        jobs.forEach { it.join() }  // wait for all
        scope.cancel()               // then cancel scope
    }
}
fun main() = runBlocking {
    val q = WorkQueue()
    repeat(3) { i -> q.submit { delay(50); println("Task $i done") } }
    q.shutdown()
    println("Queue shut down cleanly")
}

Observeerbaarheid: CoroutineName

Voorzie coroutines van het label CoroutineName voor foutopsporing. Namen verschijnen in aanroeptraceringen en kunnen in uitzonderingsafhandelaars worden gebruikt voor gestructureerde logboekregistratie.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val handler = CoroutineExceptionHandler { ctx, e ->
        println("[${ctx[CoroutineName]?.name}] Failed: ${e.message}")
    }
    CoroutineScope(SupervisorJob() + handler).apply {
        launch(CoroutineName("UserLoader")) { throw RuntimeException("DB error") }
        launch(CoroutineName("Analytics")) { delay(100); println("Analytics ok") }
        delay(200); cancel()
    }
}

Vermijd GlobalScope

Gebruik GlobalScope nooit in productie. Het maakt coroutines zonder ouder, zonder levenscyclusbeheer en zonder gestructureerde annulering. Gebruik in plaats daarvan alternatieven met een bereik.

import kotlinx.coroutines.*
// BAD — GlobalScope leaks coroutines:
// GlobalScope.launch { delay(Long.MAX_VALUE) }

// GOOD — scoped, cancellable:
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
scope.launch { delay(100); println("Scoped") }
fun main() = runBlocking { delay(200); scope.cancel() }

Veerkracht testen

Gebruik runTest met TestCoroutineScheduler om fouten, time-outs en nieuwe pogingen te simuleren in eenheidstests, zonder echte vertragingen.

import kotlinx.coroutines.*
import kotlinx.coroutines.test.*
fun testRetry() = runTest {
    var attempts = 0
    val result = retryWithBackoff(3, 100) {
        if (attempts++ < 2) throw RuntimeException("fail")
        "ok"
    }
    println(result) // "ok"
}
// In test, virtual time advances instantly through delays

Snelle controle

Welke combinatie vormt de basis van een veerkrachtig, langlevend coroutinebereik?

Samenvatting

Veerkrachtige architecturen combineren SupervisorJob voor isolatie, retryWithBackoff voor tijdelijke fouten, withTimeout voor vastgelopen I/O, finally/NonCancellable voor opruimen en CoroutineExceptionHandler voor observeerbaarheid.

Gratis beginnen

Leer Kotlin met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
51
Lessen
203

Veelgestelde vragen

Is de les “Veerkrachtige coroutinearchitecturen ontwerpen” gratis?

Ja — je kunt hier op het web alle 3 lessen van het leerpad Kotlin Academy, waaronder “Veerkrachtige coroutinearchitecturen ontwerpen”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Kotlin Academy bevat in totaal 4 lessen.

Wat leer ik in “Veerkrachtige coroutinearchitecturen ontwerpen”?

Combineer supervisorScope, retrylogica en handlers voor concurrency op productieniveau. Je oefent met Kotlin Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Kotlin Academy te beginnen?

Ervaring vooraf is niet nodig. Kotlin Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.

Hoe lang duurt de les “Veerkrachtige coroutinearchitecturen ontwerpen”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Kotlin Academy?

Ja. Elke les over Kotlin Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. SupervisorJob versus Job: fouten isoleren
  2. CoroutineExceptionHandler: globale handler voor onverwerkte exceptions
  3. Exceptionpropagatie bij async/await
  4. Veerkrachtige coroutinearchitecturen ontwerpen
← Terug naar Kotlin Academy