Что такое structured concurrency

Ответ

Structured concurrency — это подход к управлению потоками/корутинами, где их жизненные циклы строго вложены в родительскую область. Основные принципы:

  1. Иерархия — дочерние корутины завершаются до завершения родительской.
  2. Отмена — отмена родителя автоматически отменяет всех потомков.
  3. Обработка ошибок — исключение в дочерней корутине отменяет родителя и остальных потомков.

Пример с Kotlin корутинами:

scope.launch { // родитель
    launch { // дочерняя 1
        delay(1000)
        println("Child 1 done")
    }
    launch { // дочерняя 2
        delay(500)
        throw Exception("Oops!")
    }
}
// При ошибке в child 2, child 1 автоматически отменится

Преимущества: предсказуемость, отсутствие утечек, упрощение отладки.

Ответ 18+ 🔞

Давай разжую эту тему, как будто объясняю приятелю за пивом. Представь, что ты — главный по стройке. У тебя есть задача (родительская корутина), и ты нанимаешь двух работяг (дочерние корутины).

Твоя главная задача — построить сарай. Первый работяга кладёт кирпичи, второй — стелит крышу. И тут, ёпта, второй такой: «Ой, всё!» — и падает с лесов, потому что гвоздь кривой забил (бросает исключение Exception("Oops!")).

Так вот, structured concurrency — это железное правило: если один работяга накрылся медным тазом, вся стройка немедленно останавливается. Ты не можешь просто так оставить первого чувака одного достраивать сарай, пока второй в гипсе. Всё, приехали. Родительская задача (постройка сарая) отменяется, и все подчинённые процессы (оба работяги) получают команду «Всё, свободны!».

Иерархия, блядь, святая! Дочерние корутины живут ровно столько, сколько живёт их родитель. Родитель завершился — всем детям капут. Это как в той поговорке: я тебя породил, я тебя и отменю. Отмена родителя — это волшебный пендель, который летит по всей цепочке потомков. Удивление пиздец, но это работает.

А теперь смотри на код, тут всё наглядно:

scope.launch { // родитель — прораб
    launch { // дочерняя 1 — каменщик
        delay(1000)
        println("Child 1 done") // Вряд ли он это скажет, честно
    }
    launch { // дочерняя 2 — кровельщик-распиздяй
        delay(500)
        throw Exception("Oops!") // Всё, понеслась!
    }
}
// Как только второй выкинет эту хуйню, первого тут же прервут. Доверия к системе — ноль, но так и задумано.

В чём, собственно, соль? А соль в том, что у тебя не останется забытых, зависших процессов, которые тихо жрут память в углу. Нет утечек — и отладка превращается из адского квеста во вполне терпимое занятие. Всё предсказуемо, как восход солнца. Ошибка в одном месте — и весь связанный блок операций аккуратно и гарантированно сворачивается. Красота, ядрёна вошь!

Короче, если раньше твои асинхронные вызовы были как стая котов, которых выпустили погулять и которые потом не возвращаются, то structured concurrency — это прочный поводок и чёткая команда «Ко мне!». Или, в нашем случае, «На хуй!», если что-то пошло не так.