github.com/0xsequence/ethkit@v1.25.0/util/channel.go (about)

     1  package util
     2  
     3  import "github.com/goware/logger"
     4  
     5  // NOTE: please see https://github.com/goware/channel for an improved version of the below method.
     6  //
     7  // converts a blocking unbuffered send channel into a non-blocking unbounded buffered one
     8  // inspired by https://medium.com/capital-one-tech/building-an-unbounded-channel-in-go-789e175cd2cd
     9  func MakeUnboundedChan[V any](sendCh chan<- V, log logger.Logger, bufferLimitWarning int) chan<- V {
    10  	ch := make(chan V)
    11  
    12  	go func() {
    13  		var buffer []V
    14  
    15  		for {
    16  			if len(buffer) == 0 {
    17  				if message, ok := <-ch; ok {
    18  					buffer = append(buffer, message)
    19  					if len(buffer) > bufferLimitWarning {
    20  						log.Warnf("channel buffer holds %v > %v messages", len(buffer), bufferLimitWarning)
    21  					}
    22  				} else {
    23  					close(sendCh)
    24  					break
    25  				}
    26  			} else {
    27  				select {
    28  				case sendCh <- buffer[0]:
    29  					buffer = buffer[1:]
    30  
    31  				case message, ok := <-ch:
    32  					if ok {
    33  						buffer = append(buffer, message)
    34  						if len(buffer) > bufferLimitWarning {
    35  							log.Warnf("channel buffer holds %v > %v messages", len(buffer), bufferLimitWarning)
    36  						}
    37  					}
    38  				}
    39  			}
    40  		}
    41  	}()
    42  
    43  	return ch
    44  }