This gist provides a simple way to try out graceful termination
If any errors are there feel free to comment down below, I happy to fix them 👍
| package main | |
| import ( | |
| "context" | |
| "errors" | |
| "log" | |
| "math/rand" | |
| "os/signal" | |
| "strconv" | |
| "sync" | |
| "syscall" | |
| "time" | |
| ) | |
| type DB struct { | |
| wg sync.WaitGroup | |
| lock sync.RWMutex | |
| } | |
| func (db *DB) Write() { | |
| db.lock.Lock() | |
| db.wg.Add(1) | |
| defer db.lock.Unlock() | |
| defer db.wg.Done() | |
| time.Sleep(time.Duration(rand.Intn(5)) * time.Second) | |
| log.Println("WRITE") | |
| } | |
| func (db *DB) Read() { | |
| db.lock.RLock() | |
| db.wg.Add(1) | |
| defer db.lock.RUnlock() | |
| defer db.wg.Done() | |
| time.Sleep(time.Duration(rand.Intn(2)) * time.Second) | |
| log.Println("READ") | |
| } | |
| type MainLoop struct { | |
| db *DB | |
| } | |
| func (m *MainLoop) Cleanup() { | |
| log.Println("[[STOP is triggered]]") | |
| m.db.Write() | |
| m.db.wg.Wait() | |
| } | |
| type Abcd struct { | |
| Name string | |
| } | |
| func main() { | |
| ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) | |
| ctx, cancel = context.WithTimeout(ctx, time.Duration(20*time.Second)) | |
| resultsCh := make(chan *Abcd, 1) | |
| mainLoop := &MainLoop{db: &DB{}} | |
| i := 0 | |
| for { | |
| select { | |
| case <-ctx.Done(): | |
| if err := ctx.Err(); err != nil && !errors.Is(err, context.Canceled) { | |
| log.Printf("Reason of termination: %s\n", err) | |
| } | |
| log.Println("Context got cancelled") | |
| mainLoop.Cleanup() | |
| return | |
| case result := <-resultsCh: | |
| log.Printf("%#+v\n", result) | |
| default: | |
| if i > 20 { | |
| log.Println("normal termination") | |
| cancel() | |
| continue | |
| } | |
| log.Println("Waiting...", i) | |
| mainLoop.Work(resultsCh, i) | |
| i++ | |
| } | |
| } | |
| } | |
| func (m *MainLoop) Work(data chan *Abcd, i int) { | |
| switch i { | |
| case 10, 20: | |
| data <- &Abcd{Name: "Dipankar" + strconv.Itoa(i)} | |
| m.db.Write() | |
| default: | |
| m.db.Read() | |
| } | |
| } |