Завершение контекста длинного цикла в подпрограмме go - PullRequest
0 голосов
/ 03 мая 2018

Я реализую функцию, где мне нужно читать файлы из каталога, анализировать и экспортировать их в службу REST через регулярные промежутки времени. Как часть того же, я хотел бы изящно обработать завершение программы (SIGKILL, SIGQUIT и т. Д.). В связи с этим я хотел бы знать, как реализовать контекстную отмену процесса.

Для выполнения потока через регулярные промежутки времени я использую gocron.

CMD / scheduler.go

func scheduleTask(){
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()
    s := gocron.NewScheduler()
    s.Every(10).Minutes().Do(processTask, ctx)
    s.RunAll()  // run immediate
    <-s.Start() // schedule
    for {
        select {
        case <-(ctx).Done():
            fmt.Print("context done")
            s.Remove(processTask)
            s.Clear()
            cancel()
        default:
        }
    }
}   
func processTask(ctx *context.Context){
  task.Export(ctx)
}

Задача / export.go

func Export(ctx *context.Context){
   pendingFiles, err := filepath.Glob("/tmp/pending/" + "*_task.json")
   //error handling
   //as there can be 100s of files, I would like to break the loop when context.Done() to return asap & clean up the resources here as well
   for _, fileName := range pendingFiles {

    exportItem(fileName string)
   }
}

func exportItem(fileName string){
    data, err := ReadFile(fileName)  //not shown here for brevity
    //err handling
    err = postHTTPData(string(data)) //not shown for brevity
    //err handling
}

1 Ответ

0 голосов
/ 03 мая 2018

Для управления процессом, я думаю, другим компонентом является фактическая обработка сигналов и управление контекстом из этих сигналов.

Я не уверен в специфике go-cron ( у них есть пример, показывающий некоторые из этих концепций на их github ), но в целом я думаю, что следующие шаги:

  • Регистрация обработчика ос-сигналов
  • Ожидание получения сигнала
  • Отмена контекста верхнего уровня в ответ на сигнал

Пример:

sigCh := make(chan os.Signal, 1)
defer close(sigCh)
signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT)
<-sigCh
cancel()

Я не уверен, как это будет выглядеть в контексте go-cron, но контекст, который отменяет код обработки сигнала, должен быть родительским для контекста, который задаются заданием и заданием.

...