github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/services/remotecluster/send.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package remotecluster
     5  
     6  import (
     7  	"context"
     8  	"hash/fnv"
     9  )
    10  
    11  // enqueueTask adds a task to one of the send channels based on remoteId.
    12  //
    13  // There are a number  of send channels (`MaxConcurrentSends`) to allow for sending to multiple
    14  // remotes concurrently, while preserving message order for each remote.
    15  func (rcs *Service) enqueueTask(ctx context.Context, remoteId string, task interface{}) error {
    16  	if ctx == nil {
    17  		ctx = context.Background()
    18  	}
    19  
    20  	h := hash(remoteId)
    21  	idx := h % uint32(len(rcs.send))
    22  
    23  	select {
    24  	case rcs.send[idx] <- task:
    25  		return nil
    26  	case <-ctx.Done():
    27  		return NewBufferFullError(cap(rcs.send))
    28  	}
    29  }
    30  
    31  func hash(s string) uint32 {
    32  	h := fnv.New32a()
    33  	h.Write([]byte(s))
    34  	return h.Sum32()
    35  }
    36  
    37  // sendLoop is called by each goroutine created for the send pool and waits for sendTask's until the
    38  // done channel is signalled.
    39  //
    40  // Each goroutine in the pool is assigned a specific channel, and tasks are placed in the
    41  // channel corresponding to the remoteId.
    42  func (rcs *Service) sendLoop(idx int, done chan struct{}) {
    43  	for {
    44  		select {
    45  		case t := <-rcs.send[idx]:
    46  			switch task := t.(type) {
    47  			case sendMsgTask:
    48  				rcs.sendMsg(task)
    49  			case sendFileTask:
    50  				rcs.sendFile(task)
    51  			case sendProfileImageTask:
    52  				rcs.sendProfileImage(task)
    53  			}
    54  		case <-done:
    55  			return
    56  		}
    57  	}
    58  }