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 }