package web
import (
"context"
"fmt"
"sync"
"time"
)
// Hook 是一个钩子函数。注意,
// ctx 是一个有超时机制的 context.Context
// 所以你必须处理超时的问题
type Hook func(ctx context.Context) error
// BuildCloseServerHook 这里其实可以考虑使用 errgroup,
// 但是我们这里不用是希望每个 server 单独关闭
// 互相之间不影响
func BuildCloseServerHook(servers ...Server) Hook {
return func(ctx context.Context) error {
// 确保并发任务的同步
wg := sync.WaitGroup{}
// 确保所有server的关闭
doneCh := make(chan struct{})
// 添加要等待的goroutine个数
wg.Add(len(servers))
for _, s := range servers {
// 我的server都是独立的,所以开协程关闭就行了
go func(svr Server) {
err := svr.Shutdown(ctx)
if err != nil {
fmt.Printf("server shutdown error: %v \n", err)
}
time.Sleep(time.Second)
// 每关一个server,那么咱就减一
wg.Done()
}(s)
}
go func() {
// 阻塞,确保所有协程关闭
wg.Wait()
doneCh <- struct{}{}
}()
select {
case <-ctx.Done():
// 超时
fmt.Printf("closing servers timeout \n")
return ErrorHookTimeout
case <-doneCh:
// 关闭成功
fmt.Printf("close all servers \n")
return nil
}
}
}
并发编程go
最新推荐文章于 2024-10-16 18:55:04 发布