// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. package remotecluster import ( "context" "hash/fnv" ) // enqueueTask adds a task to one of the send channels based on remoteId. // // There are a number of send channels (`MaxConcurrentSends`) to allow for sending to multiple // remotes concurrently, while preserving message order for each remote. func (rcs *Service) enqueueTask(ctx context.Context, remoteId string, task any) error { if ctx == nil { ctx = context.Background() } h := hash(remoteId) idx := h % uint32(len(rcs.send)) select { case rcs.send[idx] <- task: return nil case <-ctx.Done(): return NewBufferFullError(cap(rcs.send)) } } func hash(s string) uint32 { h := fnv.New32a() h.Write([]byte(s)) return h.Sum32() } // sendLoop is called by each goroutine created for the send pool and waits for sendTask's until the // done channel is signalled. // // Each goroutine in the pool is assigned a specific channel, and tasks are placed in the // channel corresponding to the remoteId. func (rcs *Service) sendLoop(idx int, done chan struct{}) { for { select { case t := <-rcs.send[idx]: switch task := t.(type) { case sendMsgTask: rcs.sendMsg(task) case sendFileTask: rcs.sendFile(task) case sendProfileImageTask: rcs.sendProfileImage(task) } case <-done: return } } }