gitee.com/sy_183/go-common@v1.0.5-0.20231205030221-958cfe129b47/lifecycle/list.go (about)

     1  package lifecycle
     2  
     3  import (
     4  	"gitee.com/sy_183/go-common/assert"
     5  	"gitee.com/sy_183/go-common/lock"
     6  	"sync"
     7  	"sync/atomic"
     8  )
     9  
    10  const ListFieldName = "$list"
    11  
    12  type ListLifecycleHolder struct {
    13  	Lifecycle
    14  	index int
    15  	list  *List
    16  
    17  	closeAllOnStartError  atomic.Bool
    18  	closeAllOnExit        atomic.Bool
    19  	closeAllOnExitError   atomic.Bool
    20  	stopStartOnStartError atomic.Bool
    21  	closeBackOnExit       atomic.Bool
    22  	closeBackOnExitError  atomic.Bool
    23  }
    24  
    25  func (h *ListLifecycleHolder) List() *List {
    26  	return h.list
    27  }
    28  
    29  func (h *ListLifecycleHolder) SetCloseAllOnStartError(enable bool) *ListLifecycleHolder {
    30  	h.closeAllOnStartError.Store(enable)
    31  	return h
    32  }
    33  
    34  func (h *ListLifecycleHolder) SetCloseAllOnExit(enable bool) *ListLifecycleHolder {
    35  	h.closeAllOnExit.Store(enable)
    36  	return h
    37  }
    38  
    39  func (h *ListLifecycleHolder) SetCloseAllOnExitError(enable bool) *ListLifecycleHolder {
    40  	h.closeAllOnExitError.Store(enable)
    41  	return h
    42  }
    43  
    44  func (h *ListLifecycleHolder) SetStopStartOnStartError(enable bool) *ListLifecycleHolder {
    45  	h.stopStartOnStartError.Store(enable)
    46  	return h
    47  }
    48  
    49  func (h *ListLifecycleHolder) SetCloseBackOnExit(enable bool) *ListLifecycleHolder {
    50  	h.closeBackOnExit.Store(enable)
    51  	return h
    52  }
    53  
    54  func (h *ListLifecycleHolder) SetCloseBackOnExitError(enable bool) *ListLifecycleHolder {
    55  	h.closeBackOnExitError.Store(enable)
    56  	return h
    57  }
    58  
    59  type (
    60  	listLifecycleContext = childLifecycleContext[*ListLifecycleHolder]
    61  	listLifecycleChannel = childLifecycleChannel[*ListLifecycleHolder]
    62  )
    63  
    64  type List struct {
    65  	Lifecycle
    66  	lifecycle *DefaultLifecycle
    67  
    68  	children     []*ListLifecycleHolder
    69  	childrenLock sync.Mutex
    70  	started      int
    71  
    72  	closedChannel *listLifecycleChannel
    73  }
    74  
    75  func NewList() *List {
    76  	l := &List{
    77  		closedChannel: newChildLifecycleChannel[*ListLifecycleHolder](),
    78  	}
    79  	l.lifecycle = NewWithInterruptedStart(l.start)
    80  	l.Lifecycle = l.lifecycle
    81  	return l
    82  }
    83  
    84  func (l *List) Append(lifecycle Lifecycle) (*ListLifecycleHolder, error) {
    85  	return lock.RLockGetDouble(l.lifecycle, func() (*ListLifecycleHolder, error) {
    86  		if !l.lifecycle.Closed() {
    87  			return nil, NewStateNotClosedError("")
    88  		}
    89  		child := &ListLifecycleHolder{
    90  			Lifecycle: lifecycle,
    91  			index:     len(l.children),
    92  			list:      l,
    93  		}
    94  		child.SetCloseAllOnStartError(true)
    95  		child.SetCloseAllOnExit(true)
    96  		child.SetCloseAllOnExitError(true)
    97  		child.SetStopStartOnStartError(true)
    98  		child.SetCloseBackOnExit(true)
    99  		child.SetCloseBackOnExitError(true)
   100  		child.SetField(ListFieldName, l)
   101  		l.children = append(l.children, child)
   102  		return child, nil
   103  	})
   104  }
   105  
   106  func (l *List) MustAppend(lifecycle Lifecycle) *ListLifecycleHolder {
   107  	return assert.Must(l.Append(lifecycle))
   108  }
   109  
   110  func (l *List) shutdownChildren(children []*ListLifecycleHolder, exclude map[*ListLifecycleHolder]struct{}) {
   111  	excluded := func(child *ListLifecycleHolder) bool {
   112  		if exclude != nil {
   113  			_, has := exclude[child]
   114  			return has
   115  		}
   116  		return false
   117  	}
   118  	for i := len(children) - 1; i >= 0; i-- {
   119  		if !excluded(children[i]) {
   120  			future := make(ChanFuture[error], 1)
   121  			children[i].Close(future)
   122  			<-future
   123  		}
   124  	}
   125  }
   126  
   127  func (l *List) handleClosedSignal() (closeAll bool) {
   128  	closeBackIndex := -1
   129  	contexts := l.closedChannel.Pop()
   130  	var closedSet map[*ListLifecycleHolder]struct{}
   131  	for _, ctx := range contexts {
   132  		child := ctx.Lifecycle
   133  		if ctx.err != nil {
   134  			if child.closeAllOnExit.Load() || child.closeAllOnExitError.Load() {
   135  				closeAll = true
   136  			} else if child.closeBackOnExit.Load() || child.closeBackOnExitError.Load() {
   137  				if child.index < 0 || child.index < closeBackIndex {
   138  					closeBackIndex = child.index
   139  				}
   140  			}
   141  		} else {
   142  			if child.closeAllOnExit.Load() {
   143  				closeAll = true
   144  			} else if child.closeBackOnExit.Load() {
   145  				if child.index < 0 || child.index < closeBackIndex {
   146  					closeBackIndex = child.index
   147  				}
   148  			}
   149  		}
   150  		if closedSet == nil {
   151  			closedSet = make(map[*ListLifecycleHolder]struct{})
   152  		}
   153  		closedSet[child] = struct{}{}
   154  	}
   155  	if closeBackIndex >= 0 {
   156  		l.shutdownChildren(l.children[closeBackIndex+1:l.started], closedSet)
   157  	} else if closeAll {
   158  		l.shutdownChildren(l.children[:l.started], closedSet)
   159  	}
   160  	return
   161  }
   162  
   163  func (l *List) start(_ Lifecycle, interrupter chan struct{}) (runFn InterruptedRunFunc, err error) {
   164  	defer func() {
   165  		if err != nil {
   166  			l.reset()
   167  		}
   168  	}()
   169  
   170  next:
   171  	for i, child := range l.children {
   172  		future := make(ChanFuture[error], 1)
   173  		child.AddStartedFuture(future)
   174  		child.Background()
   175  		l.started = i + 1
   176  		for {
   177  			select {
   178  			case err := <-future:
   179  				if err != nil {
   180  					if child.closeAllOnStartError.Load() {
   181  						l.shutdownChildren(l.children[:l.started], nil)
   182  						return nil, NewInterruptedError("生命周期列表", "启动")
   183  					} else if child.stopStartOnStartError.Load() {
   184  						return l.run, nil
   185  					}
   186  				} else {
   187  					child.AddClosedFuture(listLifecycleContext{
   188  						Lifecycle: child,
   189  						channel:   l.closedChannel,
   190  					})
   191  				}
   192  				continue next
   193  			case <-l.closedChannel.Signal():
   194  				if l.handleClosedSignal() {
   195  					return nil, NewInterruptedError("生命周期列表", "启动")
   196  				}
   197  			case <-interrupter:
   198  				l.shutdownChildren(l.children[:l.started], nil)
   199  				return nil, NewInterruptedError("生命周期列表", "启动")
   200  			}
   201  		}
   202  	}
   203  	return l.run, nil
   204  }
   205  
   206  func (l *List) run(_ Lifecycle, interrupter chan struct{}) error {
   207  	defer l.reset()
   208  	for {
   209  		select {
   210  		case <-l.closedChannel.Signal():
   211  			if l.handleClosedSignal() {
   212  				return nil
   213  			}
   214  		case <-interrupter:
   215  			l.shutdownChildren(l.children, nil)
   216  			return nil
   217  		}
   218  	}
   219  }
   220  
   221  func (l *List) reset() {
   222  	l.started = 0
   223  	l.closedChannel = newChildLifecycleChannel[*ListLifecycleHolder]()
   224  }