Using the blocking mechanism of chan to realize the start, blocking and return controller of the cooperation process

I. use scenarios The background is to read oplog from kafka for incremental processing, but when I want to send a command to block the incremental pro...

I. use scenarios

The background is to read oplog from kafka for incremental processing, but when I want to send a command to block the incremental process, and then start a full synchronization, I will continue incremental processing.

Therefore, multiple processes need to be controlled.

II. Use knowledge

1. Reading from an uninitialized pipeline will block

2. Reading from a closed pipe will not block

Control with two pipes and select

III. code above

Controller code

package util import ( "errors" "sync" ) const ( //STOP stop STOP = iota //START start START //PAUSE pause PAUSE ) //Control controller type Control struct { ch1 chan struct{} ch2 chan struct{} stat int64 lock sync.RWMutex } var ( //ErrStat error status ErrStat = errors.New("stat error") ) //NewControl gets a new Control func NewControl() *Control { return &Control{ ch1: make(chan struct{}), ch2: nil, stat: START, lock: sync.RWMutex{}, } } //Stop stop func (c *Control) Stop() error { c.lock.Lock() defer c.lock.Unlock() if c.stat == START { c.ch2 = nil close(c.ch1) c.stat = STOP } else if c.stat == PAUSE { ch2 := c.ch2 c.ch2 = nil close(c.ch1) close(ch2) c.stat = STOP } else { return ErrStat } return nil } //Pause pause func (c *Control) Pause() error { c.lock.Lock() defer c.lock.Unlock() if c.stat == START { c.ch2 = make(chan struct{}) close(c.ch1) c.stat = PAUSE } else { return ErrStat } return nil } //Start start func (c *Control) Start() error { c.lock.Lock() defer c.lock.Unlock() if c.stat == PAUSE { c.ch1 = make(chan struct{}) close(c.ch2) c.stat = START } else { return ErrStat } return nil } //C control pipe func (c *Control) C() <-chan struct{} { c.lock.RLock() defer c.lock.RUnlock() return c.ch1 } //Wait waiting func (c *Control) Wait() bool { c.lock.RLock() ch2 := c.ch2 c.lock.RUnlock() if ch2 == nil { //Send stop push command by assigning nil return false } <-ch2 //Will block return true }

Use code

for { select { case part, ok := <-c.Partitions(): if !ok { conf.Logger.Error("get kafka Partitions not ok", regular.Name) return } go readFromPart(c, part, regular, respChan) case <-regular.C(): //regular is a Control class if !regular.Wait() { conf.Logger.Debug("Stop! ") return } conf.Logger.Debug("Start! ") } }

In this way, you can control the cooperation in the project anytime and anywhere

regular := util.NewControl() regular.Pause() regular.Start() regular.Stop()

3 December 2019, 20:43 | Views: 4272

Add new comment

For adding a comment, please log in
or create account

0 comments