Go Academy · Урок

Корректное завершение задач

Корректно останавливайте задачи

Урок 4 из 413 шагов

«Корректное завершение задач» — бесплатный урок Go Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

Корректная остановка заданий

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

Ожидание сигналов

Перехватывайте сигналы OS, такие как SIGINT (Ctrl+C) и SIGTERM (остановка оркестратором), чтобы намеренно завершать работу.

sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
<-sig
fmt.Println("shutting down")

signal.NotifyContext

Начиная с Go 1.16, доступен удобный вспомогательный механизм, который отменяет контекст при поступлении сигнала.

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
<-ctx.Done()

Остановка планировщика

В robfig/cron вызов c.Stop() возвращает контекст, который завершается после окончания всех выполняющихся заданий. Дождитесь его, чтобы дать заданиям завершиться.

ctx := c.Stop()        // stops scheduling, returns ctx
<-ctx.Done()            // wait for running jobs
fmt.Println("all jobs finished")

Передача отмены заданиям

Передавайте контекст каждому заданию, чтобы длительная работа могла быстро прерваться после начала завершения.

func job(ctx context.Context) {
    select {
    case <-time.After(time.Hour):
    case <-ctx.Done():
        return // bail out early
    }
}

Ограничение времени ожидания

Не ждите зависших заданий бесконечно. Используйте контекст с ограничением времени, чтобы завершение произошло даже в случае зависания задания.

shutCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

WaitGroups для собственных планировщиков

Если Вы создаёте планировщик самостоятельно с помощью горутин, отслеживайте их через sync.WaitGroup и вызывайте Wait() во время завершения.

var wg sync.WaitGroup
wg.Add(1)
go func() { defer wg.Done(); doWork() }()
// shutdown:
wg.Wait()

Не начинайте новую работу

После начала завершения тикер или планировщик должны перестать срабатывать. Закрытие канала завершения или отмена контекста позволяет циклу увидеть сигнал и прекратить планирование новых запусков.

Идемпотентность помогает

Проектируйте задания так, чтобы их было безопасно запускать повторно. Если задание было прервано в середине выполнения и повторно запущено после перезапуска, идемпотентная логика предотвращает повторные эффекты, например повторную отправку писем или двойное списание средств.

Полный шаблон

Объединим всё вместе: контекст, который уведомляется о сигнале, вызов Stop у cron, возвращающий контекст ожидания завершения, и ограничение времени ожидания. Это стандартный каркас корректного завершения сервисов с запланированными заданиями.

Готовый к запуску пример: корректная остановка с контекстом

Эта автономная программа запускает периодический обработчик и корректно останавливает его через отмену контекста, дожидаясь завершения текущего сигнала тикера.

package main

import (
    "context"
    "fmt"
    "sync"
    "time"
)

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        t := time.NewTicker(5 * time.Millisecond)
        defer t.Stop()
        for {
            select {
            case <-t.C:
                fmt.Println("working")
            case <-ctx.Done():
                fmt.Println("stopping cleanly")
                return
            }
        }
    }()
    time.Sleep(17 * time.Millisecond)
    cancel()   // signal shutdown
    wg.Wait()  // wait for worker to finish
    fmt.Println("shutdown complete")
}

Проверка знаний

Проверьте, насколько хорошо Вы поняли корректное завершение заданий.

Итоги

Вы изучили корректное завершение заданий:

  • Перехватывайте SIGINT/SIGTERM, желательно через signal.NotifyContext
  • cron.Stop() возвращает контекст, который дожидается завершения выполняющихся заданий
  • Передавайте контекст заданиям и ограничивайте время ожидания с помощью таймера
  • Делайте задания идемпотентными, чтобы их повторные запуски были безопасными
Можно начать бесплатно

Изучай Go с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
51
Уроки
203

Часто задаваемые вопросы

Урок «Корректное завершение задач» бесплатный?

Да — полный текст урока «Корректное завершение задач» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «Корректное завершение задач»?

Корректно останавливайте задачи Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Корректное завершение задач»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Планирование по времени
  2. Библиотека robfig/cron
  3. Тикеры для интервалов
  4. Корректное завершение задач
← Назад к Go Academy