1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-09-17 10:16:57 +00:00

Add ratelimits to publishing

This commit is contained in:
Kane York 2017-02-02 22:59:17 -08:00
parent b84bd1d4a2
commit 50e295c834
10 changed files with 260 additions and 103 deletions

View file

@ -11,7 +11,7 @@ import (
type SubscriberList struct {
sync.RWMutex
Members []chan<- ClientMessage
Members []*ClientInfo
}
var ChatSubscriptionInfo map[string]*SubscriberList = make(map[string]*SubscriberList)
@ -19,6 +19,18 @@ var ChatSubscriptionLock sync.RWMutex
var GlobalSubscriptionInfo []*ClientInfo
var GlobalSubscriptionLock sync.RWMutex
func (client *ClientInfo) Send(msg ClientMessage) bool {
select {
case client.MessageChannel <- msg:
return true
case <-client.MsgChannelIsDone:
return false
default:
// if we can't immediately send, ignore it
return false
}
}
func CountSubscriptions(channels []string) int {
ChatSubscriptionLock.RLock()
defer ChatSubscriptionLock.RUnlock()
@ -38,70 +50,77 @@ func CountSubscriptions(channels []string) int {
func SubscribeChannel(client *ClientInfo, channelName string) {
ChatSubscriptionLock.RLock()
_subscribeWhileRlocked(channelName, client.MessageChannel)
_subscribeWhileRlocked(channelName, client)
ChatSubscriptionLock.RUnlock()
}
func SubscribeDefaults(client *ClientInfo) {
}
func SubscribeGlobal(client *ClientInfo) {
GlobalSubscriptionLock.Lock()
AddToSliceCl(&GlobalSubscriptionInfo, client)
GlobalSubscriptionLock.Unlock()
}
func PublishToChannel(channel string, msg ClientMessage) (count int) {
func PublishToChannel(channel string, msg ClientMessage, rl RateLimit) (count int) {
var found []*ClientInfo
ChatSubscriptionLock.RLock()
list := ChatSubscriptionInfo[channel]
if list != nil {
list.RLock()
for _, msgChan := range list.Members {
msgChan <- msg
count++
}
found = make([]*ClientInfo, len(list.Members))
copy(found, list.Members)
list.RUnlock()
}
ChatSubscriptionLock.RUnlock()
for _, cl := range found {
rl.Performed()
if cl.Send(msg) {
count++
}
}
return
}
func PublishToMultiple(channels []string, msg ClientMessage) (count int) {
found := make(map[chan<- ClientMessage]struct{})
func PublishToMultiple(channels []string, msg ClientMessage, rl RateLimit) (count int) {
var found []*ClientInfo
ChatSubscriptionLock.RLock()
for _, channel := range channels {
list := ChatSubscriptionInfo[channel]
if list != nil {
list.RLock()
for _, msgChan := range list.Members {
found[msgChan] = struct{}{}
for _, cl := range list.Members {
found = append(found, cl)
}
list.RUnlock()
}
}
ChatSubscriptionLock.RUnlock()
for msgChan, _ := range found {
msgChan <- msg
count++
for _, cl := range found {
rl.Performed()
if cl.Send(msg) {
count++
}
}
return
return count
}
func PublishToAll(msg ClientMessage) (count int) {
func PublishToAll(msg ClientMessage, rl RateLimit) (count int) {
var found []*ClientInfo
GlobalSubscriptionLock.RLock()
for _, client := range GlobalSubscriptionInfo {
select {
case client.MessageChannel <- msg:
case <-client.MsgChannelIsDone:
}
count++
}
found = make([]*ClientInfo, len(GlobalSubscriptionInfo))
copy(found, GlobalSubscriptionInfo)
GlobalSubscriptionLock.RUnlock()
for _, cl := range found {
rl.Performed()
if cl.Send(msg) {
count++
}
}
return
}
@ -110,7 +129,7 @@ func UnsubscribeSingleChat(client *ClientInfo, channelName string) {
list := ChatSubscriptionInfo[channelName]
if list != nil {
list.Lock()
RemoveFromSliceC(&list.Members, client.MessageChannel)
RemoveFromSliceCl(&list.Members, client)
list.Unlock()
}
ChatSubscriptionLock.RUnlock()
@ -138,7 +157,7 @@ func UnsubscribeAll(client *ClientInfo) {
list := ChatSubscriptionInfo[v]
if list != nil {
list.Lock()
RemoveFromSliceC(&list.Members, client.MessageChannel)
RemoveFromSliceCl(&list.Members, client)
list.Unlock()
}
}
@ -191,14 +210,14 @@ func pubsubJanitor_do() {
// - ALREADY HOLDING a read-lock to the 'which' top-level map via the rlocker object
// - possible write lock to the 'which' top-level map via the wlocker object
// - write lock to SubscriptionInfo (if not creating new)
func _subscribeWhileRlocked(channelName string, value chan<- ClientMessage) {
func _subscribeWhileRlocked(channelName string, value *ClientInfo) {
list := ChatSubscriptionInfo[channelName]
if list == nil {
// Not found, so create it
ChatSubscriptionLock.RUnlock()
ChatSubscriptionLock.Lock()
list = &SubscriberList{}
list.Members = []chan<- ClientMessage{value} // Create it populated, to avoid reaper
list.Members = []*ClientInfo{value} // Create it populated, to avoid reaper
ChatSubscriptionInfo[channelName] = list
ChatSubscriptionLock.Unlock()
@ -212,7 +231,7 @@ func _subscribeWhileRlocked(channelName string, value chan<- ClientMessage) {
ChatSubscriptionLock.RLock()
} else {
list.Lock()
AddToSliceC(&list.Members, value)
AddToSliceCl(&list.Members, value)
list.Unlock()
}
}