Graceful Shutdown
Yumshoq to'xtatish (Graceful Shutdown)
"Graceful Shutdown" darsini (Cloud Patterns kursida) eslang: serverni to'satdan o'chirish o'rniga, unga "tugatishga tayyorlaning" deb ELCHI yuborib, joriy ishlarni YAKUNLASHGA vaqt berish kerak. Task Queue uchun bu AYNIQSA muhim: agar server worker'lar hali vazifa bajarayotganda TO'SATDAN o'chirilsa, o'sha vazifalar YO'QOLADI — hech qachon tugallanmaydi.
package main
import (
"context"
"fmt"
"sync"
"time"
)
type Task struct {
ID string
}
// worker — context bekor qilinganda ISHNI TO'XTATADI, lekin
// joriy vazifani hali ham TUGATADI
func worker(ctx context.Context, tasks <-chan *Task, wg *sync.WaitGroup, processed *[]string, mu *sync.Mutex) {
defer wg.Done()
for {
select {
case task, ok := <-tasks:
if !ok {
return
}
mu.Lock()
*processed = append(*processed, task.ID)
mu.Unlock()
case <-ctx.Done():
return
}
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
defer cancel()
tasks := make(chan *Task, 3)
tasks <- &Task{ID: "task-1"}
tasks <- &Task{ID: "task-2"}
close(tasks)
var wg sync.WaitGroup
var mu sync.Mutex
var processed []string
wg.Add(1)
go worker(ctx, tasks, &wg, &processed, &mu)
wg.Wait()
fmt.Println(len(processed))
}select bilan IKKI YO'NALISHNI kuzatish — "Select Statement" darsida ko'rgan naqsh: worker HAR bir aylanishda YOKI navbatdan yangi vazifa keladimi (case task, ok := <-tasks), YOKI vaqt tugab, ctx bekor qilinganidan (case <-ctx.Done()) qaysi biri OLDIN sodir bo'lishini kuzatadi. Bu — worker'ga "vaqt tugasa ham, hozirgi ishni tashlab qochma, lekin YANGI ish qabul qilma" degan xulq-atvorni beradi.
Production'da bu g'oya odatda ikki bosqichli bo'ladi: birinchi signal kelganda "yangi vazifa qabul qilishni TO'XTAT", lekin JORIY vazifalar tugashini KUT (masalan qo'shimcha sync.WaitGroup), va faqat SHUNDAN keyin dasturni butunlay yopish. Bu — "http.Server.Shutdown" darsida ko'rgan aynan shu tamoyilning Task Queue kontekstidagi ko'rinishi.
>_ Exercise
Kontekst allaqachon bekor qilingan holatda, worker hech qanday vazifani qayta ishlamasligini tekshiring.
- •context.WithCancel bilan ctx yarating va DARHOL cancel() ni chaqiring
- •tasks kanalini BO'SH holda (hech narsa yubormasdan) qoldiring
- •worker'ni ishga tushirib, wg.Wait() qiling, so'ng len(processed)ni chop eting
Stuck? Reveal a hint to help you.
Key Takeaway
Key Takeaway:
select va context.Done() birgalikda, worker'ga "vaqt tugasa ham joriy ishni yakunlash, lekin yangi ish qabul qilmaslik" imkonini beradi — bu Task Queue'ni to'satdan emas, balki yumshoq (graceful) to'xtatish uchun zarur.
NEXT UP
Project Recap & Next Steps
$ go run main.go
Kodingizni ishga tushiring