gitee.com/sy_183/go-common@v1.0.5-0.20231205030221-958cfe129b47/lifecycle/retryable.go (about) 1 package lifecycle 2 3 import ( 4 "gitee.com/sy_183/go-common/timer" 5 "sync/atomic" 6 "time" 7 ) 8 9 const RetryableFieldName = "$retryable" 10 11 type Retryable[LIFECYCLE Lifecycle] struct { 12 Lifecycle 13 lifecycle LIFECYCLE 14 15 interrupted bool 16 17 lazyStart atomic.Bool 18 retryInterval atomic.Int64 19 } 20 21 func NewRetryable[LIFECYCLE Lifecycle](lifecycle LIFECYCLE) *Retryable[LIFECYCLE] { 22 r := &Retryable[LIFECYCLE]{ 23 lifecycle: lifecycle, 24 } 25 lifecycle.SetField(RetryableFieldName, r) 26 r.Lifecycle = NewWithInterruptedStart(r.start) 27 return r 28 } 29 30 func (r *Retryable[LIFECYCLE]) Get() LIFECYCLE { 31 return r.lifecycle 32 } 33 34 func (r *Retryable[LIFECYCLE]) SetLazyStart(lazyStart bool) *Retryable[LIFECYCLE] { 35 r.lazyStart.Store(lazyStart) 36 return r 37 } 38 39 func (r *Retryable[LIFECYCLE]) SetRetryInterval(interval time.Duration) *Retryable[LIFECYCLE] { 40 r.retryInterval.Store(int64(interval)) 41 return r 42 } 43 44 func (r *Retryable[LIFECYCLE]) start(_ Lifecycle, interrupter chan struct{}) (InterruptedRunFunc, error) { 45 var lazyStart bool 46 47 run := func(_ Lifecycle, interrupter chan struct{}) error { 48 var state State 49 runningFuture := make(ChanFuture[error], 1) 50 closedFuture := make(ChanFuture[error], 1) 51 startRetryTimer := timer.NewTimer(make(chan struct{}, 1)) 52 defer func() { 53 r.interrupted = false 54 startRetryTimer.Stop() 55 }() 56 57 if lazyStart { 58 state = StateClosed 59 startRetryTimer.Trigger() 60 } else { 61 state = StateRunning 62 r.lifecycle.AddClosedFuture(closedFuture) 63 } 64 65 for { 66 select { 67 case <-startRetryTimer.C: 68 // 如果启动了定时器,说明生命周期组件一定为关闭状态,有中断信号则直接退出,所以此处一定没有标记中断, 69 // 此时需要启动组件并添加启动完成的追踪器到组件 70 r.lifecycle.AddStartedFuture(runningFuture) 71 state = StateStarting 72 r.lifecycle.Background() 73 case err := <-runningFuture: 74 // 生命周期组件启动完成,如果启动错误,在这种情况下如果标记了中断,则直接退出,否则启动定时器,定时器 75 // 触发后执行重启。如果启动成功,不管有没有中断信号,向组件添加关闭的追踪器 76 if err != nil { 77 state.ToClosed() 78 if r.interrupted { 79 return nil 80 } 81 startRetryTimer.After(time.Duration(r.retryInterval.Load())) 82 continue 83 } 84 state.ToRunning() 85 r.lifecycle.AddClosedFuture(closedFuture) 86 case <-closedFuture: 87 // 生命周期组件退出,如果标记了中断,则直接退出,否则启动定时器,定时器触发后执行重启 88 state.ToClosed() 89 if r.interrupted { 90 return nil 91 } 92 startRetryTimer.After(time.Duration(r.retryInterval.Load())) 93 case <-interrupter: 94 // 中断信号只会出现一次,如果此时生命周期组件为关闭状态,则直接退出,否则对组件执行关闭操作 95 r.interrupted = true 96 if state.Closed() { 97 return nil 98 } 99 r.lifecycle.Close(nil) 100 } 101 } 102 } 103 104 if !r.lazyStart.Load() { 105 r.lifecycle.Background() 106 for { 107 select { 108 case err := <-r.lifecycle.StartedWaiter(): 109 if err != nil { 110 r.interrupted = false 111 } 112 return run, err 113 case <-interrupter: 114 r.interrupted = true 115 r.lifecycle.Close(nil) 116 } 117 } 118 } 119 lazyStart = true 120 return run, nil 121 }