github.com/dfklegend/cell2/utils@v0.0.0-20240402033734-a0a9f3d9335d/waterfall/waterfall_sche.go (about)

     1  package waterfall
     2  
     3  import (
     4  	scheP "github.com/dfklegend/cell2/utils/sche"
     5  )
     6  
     7  // 实现一个类似nodejs waterfall
     8  // 每个回调都在调用routine中调用
     9  
    10  type Chain struct {
    11  	// 任务列表
    12  	tasks []Task
    13  	// 最后的任务
    14  	final  FinalCallback
    15  	cursor int
    16  	// 执行
    17  	callbackFunc Callback
    18  }
    19  
    20  func (c *Chain) invokeTask(index int, args ...interface{}) {
    21  	c.tasks[index](c.callbackFunc, args...)
    22  }
    23  
    24  func (c *Chain) tryExec(index int, args ...interface{}) {
    25  	if index < len(c.tasks) {
    26  		c.invokeTask(index, args...)
    27  	} else {
    28  		c.invokeFinal(false, args...)
    29  	}
    30  }
    31  
    32  func (c *Chain) next(args ...interface{}) {
    33  	c.cursor++
    34  	c.tryExec(c.cursor, args...)
    35  }
    36  
    37  func (c *Chain) invokeFinal(err bool, args ...interface{}) {
    38  	c.final(err, args...)
    39  }
    40  
    41  func (c *Chain) invokeCallback(err bool, args ...interface{}) {
    42  	if err {
    43  		c.invokeFinal(true, args...)
    44  		return
    45  	}
    46  
    47  	// next
    48  	c.next(args...)
    49  }
    50  
    51  // 	一般远程任务,传入的回调函数,可能在其他的执行环境内触发
    52  // 	保证Task和Final都在sche内驱动执行
    53  func Sche(sche *scheP.Sche, tasks []Task, final FinalCallback) *Chain {
    54  	thisChain := &Chain{
    55  		tasks: tasks,
    56  		final: final,
    57  	}
    58  
    59  	thisChain.callbackFunc = func(err bool, args ...interface{}) {
    60  		// 去到环境中执行
    61  		sche.Post(func() {
    62  			thisChain.invokeCallback(err, args...)
    63  		})
    64  	}
    65  
    66  	sche.Post(func() {
    67  		thisChain.tryExec(0)
    68  	})
    69  	return thisChain
    70  }
    71  
    72  //	Builder of sche
    73  //	NewBuilder().Next().Next().Final().Do()
    74  type Builder struct {
    75  	sche  *scheP.Sche
    76  	tasks []Task
    77  	final FinalCallback
    78  }
    79  
    80  func NewBuilder(s *scheP.Sche) *Builder {
    81  	return &Builder{
    82  		sche:  s,
    83  		tasks: make([]Task, 0),
    84  	}
    85  }
    86  
    87  func (b *Builder) Next(task Task) *Builder {
    88  	b.tasks = append(b.tasks, task)
    89  	return b
    90  }
    91  
    92  func (b *Builder) Final(final FinalCallback) *Builder {
    93  	b.final = final
    94  	return b
    95  }
    96  
    97  func (b *Builder) Do() {
    98  	Sche(b.sche, b.tasks, b.final)
    99  }