Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

+1 467новых вакансий за сутки·93 721вакансия открыта сейчас·Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Новые вакансии в TelegramРаботодателям
Talanto
Вакансии
Компании7 267
РезюмеAIПодготовкаСтатьи
BoostТарифыBoost
Войти

Не нашли подходящее?

Пусть нужная вакансия найдёт вас сама.

  1. Подборка в TelegramНовые вакансии по вашему фильтру — сразу в бота.Подключить
  2. Мэтчи по резюмеЗагрузите резюме — покажем, где вы подходите лучше всего.Загрузить
  3. Сохранить фильтрНастройте поиск один раз и возвращайтесь к новым вакансиям.Настроить
Что нового на TalantoTalanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Для работодателей

Опубликуйте вакансию — отклики придут в ваш кабинет.

  1. Вакансиябесплатно
  2. Откликиконтакты бесплатно
  3. Наймэтапы и интервью

40 компаний публикуют вакансии напрямую · 4 401 кандидат открыт к предложениям

Разместить вакансию

Популярные направления

Все подборки
  • Python17 129
  • Облачные технологии14 088
  • QA вакансии3 457
  • Backend вакансии2 115
  • Инженер данных1 805
  • Продакт-менеджер1 262

Разработка

  • Android1 865
  • iOS1 698
  • Fullstack вакансии989
  • AI вакансии949
  • Frontend вакансии744
  • Mobile вакансии44

По стеку

  • Go8 660
  • Java6 550
  • Node.js2 020
  • .NET1 722
  • Kotlin1 619
  • Rust1 455
  • C#711
  • PHP683
  • C++572

DevOps и инфраструктура

  • Kubernetes7 769
  • DevOps вакансии6 056
  • Linux-инфраструктура5 493
  • Terraform / IaC4 266
  • CI/CD3 250
  • Мониторинг и Observability1 788
  • SRE567
  • Кибербезопасность453

Аналитика и данные

  • Data Scientist1 141
  • Бизнес-аналитик927
  • Аналитик данных854
  • Системный аналитик153

Другие направления

  • Проджект-менеджер616
  • UI/UX дизайн146
  • Ручное тестирование14

По регионам

  • Вакансии в США44 281
  • Вакансии в Европе23 875
  • Вакансии в Канаде4 475
  • Работа в России3 922

По формату

  • Удалённые вакансии75 035
  • Релокация в США44 281
  • Гибридная работа12 401
  • Офисная работа7 079

По уровню

  • Senior вакансии42 679
  • Middle вакансии20 894
  • Junior вакансии6 722

Сейчас нанимают

Все компании
  • Wise190 вакансий
  • Rakuten189 вакансий
  • ASML166 вакансий
  • Grab137 вакансий
  • Celonis39 вакансий
  • Spotify37 вакансий
  • Adyen28 вакансий
  • Infobip28 вакансий
  • Monzo20 вакансий
  • Darktrace16 вакансий

Вакансии из 344 источников: карьерные страницы компаний и джоб-борды.

КомпанииО насНовостиПубличная офертаУсловия использованияПолитика конфиденциальностиПоддержка
←К теме TokioВсе вопросы
TokioMiddleТеория

Как отменить Tokio task и что происходит, когда future прерывается в середине выполнения?

В закладки
Сначала попробуйте ответить сами30 секунд
Сравнить с ответом ↓

Задача отменяется через JoinHandle::abort() — future дропается в следующей точке .await. Деструкторы вызываются, но незавершённая логическая работа теряется. Для graceful shutdown используют CancellationToken из tokio-util.

Механизм abort()

use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
    let handle = tokio::spawn(async {
        println!("task started");
        sleep(Duration::from_secs(10)).await;   // точка прерывания
        println!("task finished");               // это не выполнится
    });

    sleep(Duration::from_millis(50)).await;
    handle.abort();

    match handle.await {
        Ok(_) => println!("completed normally"),
        Err(e) if e.is_cancelled() => println!("task was cancelled"),
        Err(e) => println!("task panicked: {e}"),
    }
}

abort() лишь помечает задачу на отмену. Реальная отмена случается в следующей точке .await внутри задачи — именно там Tokio может вернуть Poll::Pending и затем дропнуть future. Код после этой точки await никогда не выполнится.

Отмена Tokio task и поведение future при прерывании

В Tokio отмена задачи происходит через вызов JoinHandle::abort(). После этого runtime при следующей возможности дропает future задачи. Аналогично future отменяется, когда её дропают из ветки tokio::select!, которая не была выбрана, или когда JoinHandle выбрасывается без .await.

Что происходит при дропе future

Rust гарантирует вызов деструкторов (Drop) для всех значений, находившихся в стеке future в момент прерывания. Однако любая логическая работа, которая ещё не завершилась, теряется. Пример опасного сценария:

async fn transfer_funds(db: &Db, from: i64, to: i64, amount: u64) {
    db.debit(from, amount).await;   // <-- если задача отменена здесь...
    db.credit(to, amount).await;    // ...этот вызов никогда не произойдёт
}

Деньги спишутся, но не зачислятся. Решение — обернуть операцию в транзакцию БД или использовать CancellationToken с явным завершением.

CancellationToken — graceful shutdown

use tokio_util::sync::CancellationToken;
use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
    let token = CancellationToken::new();
    let child = token.clone();

    let handle = tokio::spawn(async move {
        tokio::select! {
            _ = child.cancelled() => {
                // корректная очистка
                println!("graceful shutdown");
            }
            _ = do_work() => {
                println!("work done");
            }
        }
    });

    sleep(Duration::from_millis(100)).await;
    token.cancel();         // сигнализируем задаче
    handle.await.unwrap();
}

async fn do_work() {
    sleep(Duration::from_secs(60)).await;
}

abort_handle()

Начиная с Tokio 1.17 можно получить AbortHandle отдельно от JoinHandle, что удобно, когда нужно отменить задачу, не дожидаясь её завершения:

let (handle, abort_handle) = {
    let jh = tokio::spawn(long_task());
    let ah = jh.abort_handle();
    (jh, ah)
};
// позже:
abort_handle.abort();
let _ = handle.await; // JoinError::is_cancelled() == true

Подводные камни

  • abort() не является синхронным — задача продолжает работать до следующей точки .await. Если задача зависла в CPU-bound цикле без await, она не будет отменена.
  • Дроп JoinHandle без .await отсоединяет задачу (detach), а не отменяет её — задача продолжает работать в фоне.
  • Деструкторы вызываются, но асинхронный код в Drop не выполняется — нельзя написать async fn drop. Финальная очистка требует явного паттерна (CancellationToken + select).
  • После abort() вызов handle.await обязателен для гарантии завершения задачи до выхода из runtime. Иначе runtime просто уничтожит задачу при shutdown без гарантии очистки.
  • Паника внутри задачи и отмена возвращают разные варианты JoinError: is_panic() vs is_cancelled() — различайте их явно.
  • Если задача захватывает MutexGuard из std через точку await — это deadlock; при отмене guard освобождается через Drop, но это произойдёт в асинхронном контексте без гарантий порядка.

Частые вопросы на собеседовании

  • В каких проектах Tokio (Rust) оправдан, а где он становится источником лишней сложности?
  • Какие production или build/runtime-риски есть у Tokio (Rust): воспроизводимость, совместимость, debugging, ресурсы или supply chain?
  • Как понять, что проблема связана именно с Tokio (Rust), а не с приложением, окружением, сетью или зависимостями?
  • Какие ошибки делают команды, когда используют Tokio (Rust) без понимания его модели выполнения или сборки?

Типичные ошибки

  • Отвечать определением без production-сценария.
  • Не называть runtime boundary, security boundary или failure mode.
  • Игнорировать версию API, observability и тестовую проверку.

Что проверяет интервьюер

  • Объясняет механизм своими словами и без выдуманных API.
  • Называет реальные риски, диагностику и критерий корректности.
  • Связывает ответ с текущей документацией и миграционными ограничениями.

Как вы знаете этот вопрос?

Проверить себя по теме Tokio →

Источники

  • https://docs.rs/tokio/1.49.0/tokio/
←Предыдущий вопросЧто такое `tokio::select!` и как он работает?Следующий вопрос→Каковы последствия cancellation safety в Tokio?

Связанные темы

Tokiorisk-analysistechnical-depthtokio-productionTokio (Rust)