1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-07-30 06:28:31 +00:00

Re-add bunched request caching with a lazy janitor

And this time, only one lock is held at a time during the response.
This commit is contained in:
Kane York 2015-11-15 15:52:37 -08:00
parent 377afb7a6b
commit d518759fa0
2 changed files with 81 additions and 4 deletions

View file

@ -379,12 +379,82 @@ type BunchSubscriberList struct {
Members []BunchSubscriber Members []BunchSubscriber
} }
type CacheStatus byte
const (
CacheStatusNotFound = iota
CacheStatusFound
CacheStatusExpired
)
var PendingBunchedRequests map[BunchedRequest]*BunchSubscriberList = make(map[BunchedRequest]*BunchSubscriberList) var PendingBunchedRequests map[BunchedRequest]*BunchSubscriberList = make(map[BunchedRequest]*BunchSubscriberList)
var PendingBunchLock sync.Mutex var PendingBunchLock sync.Mutex
var CachedBunchedRequests map[BunchedRequest]BunchedResponse = make(map[BunchedRequest]BunchedResponse)
var CachedBunchLock sync.RWMutex
var BunchCacheCleanupSignal *sync.Cond = sync.NewCond(&CachedBunchLock)
var BunchCacheLastCleanup time.Time
func bunchCacheJanitor() {
go func() {
for {
time.Sleep(30*time.Minute)
BunchCacheCleanupSignal.Signal()
}
}()
CachedBunchLock.Lock()
for {
// Unlocks CachedBunchLock, waits for signal, re-locks
BunchCacheCleanupSignal.Wait()
if BunchCacheLastCleanup.After(time.Now().Add(-1*time.Second)) {
// skip if it's been less than 1 second
continue
}
// CachedBunchLock is held here
keepIfAfter := time.Now().Add(-5*time.Minute)
for req, resp := range CachedBunchedRequests {
if !resp.Timestamp.After(keepIfAfter) {
delete(CachedBunchedRequests, req)
}
}
BunchCacheLastCleanup = time.Now()
// Loop and Wait(), which re-locks
}
}
func HandleBunchedRemoteCommand(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { func HandleBunchedRemoteCommand(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) {
br := BunchedRequestFromCM(&msg) br := BunchedRequestFromCM(&msg)
cacheStatus := func() byte {
CachedBunchLock.RLock()
defer CachedBunchLock.RUnlock()
bresp, ok := CachedBunchedRequests[br]
if ok && bresp.Timestamp.After(time.Now().Add(-5*time.Minute)) {
client.MsgChannelKeepalive.Add(1)
go func() {
var rmsg ClientMessage
rmsg.Command = SuccessCommand
rmsg.MessageID = msg.MessageID
rmsg.origArguments = bresp.Response
rmsg.parseOrigArguments()
client.MessageChannel <- rmsg
client.MsgChannelKeepalive.Done()
}()
return CacheStatusFound
} else if ok {
return CacheStatusExpired
}
return CacheStatusNotFound
}()
if cacheStatus == CacheStatusFound {
return ClientMessage{Command: AsyncResponseCommand}, nil
} else if cacheStatus == CacheStatusExpired {
// Wake up the lazy janitor
BunchCacheCleanupSignal.Signal()
}
PendingBunchLock.Lock() PendingBunchLock.Lock()
defer PendingBunchLock.Unlock() defer PendingBunchLock.Unlock()
list, ok := PendingBunchedRequests[br] list, ok := PendingBunchedRequests[br]
@ -399,18 +469,24 @@ func HandleBunchedRemoteCommand(conn *websocket.Conn, client *ClientInfo, msg Cl
PendingBunchedRequests[br] = &BunchSubscriberList{Members: []BunchSubscriber{{Client: client, MessageID: msg.MessageID}}} PendingBunchedRequests[br] = &BunchSubscriberList{Members: []BunchSubscriber{{Client: client, MessageID: msg.MessageID}}}
go func(request BunchedRequest) { go func(request BunchedRequest) {
resp, err := SendRemoteCommandCached(string(request.Command), request.Param, AuthInfo{}) respStr, err := SendRemoteCommandCached(string(request.Command), request.Param, AuthInfo{})
var msg ClientMessage var msg ClientMessage
if err == nil { if err == nil {
msg.Command = SuccessCommand msg.Command = SuccessCommand
msg.origArguments = resp msg.origArguments = respStr
msg.parseOrigArguments() msg.parseOrigArguments()
} else { } else {
msg.Command = ErrorCommand msg.Command = ErrorCommand
msg.Arguments = err.Error() msg.Arguments = err.Error()
} }
if err == nil {
CachedBunchLock.Lock()
CachedBunchedRequests[request] = BunchedResponse{Response: respStr, Timestamp: time.Now()}
CachedBunchLock.Unlock()
}
PendingBunchLock.Lock() PendingBunchLock.Lock()
bsl := PendingBunchedRequests[request] bsl := PendingBunchedRequests[request]
delete(PendingBunchedRequests, request) delete(PendingBunchedRequests, request)

View file

@ -73,9 +73,10 @@ func SetupServerAndHandle(config *ConfigFile, serveMux *http.ServeMux) {
resp.Body.Close() resp.Body.Close()
} }
go pubsubJanitor()
go backlogJanitor()
go authorizationJanitor() go authorizationJanitor()
go backlogJanitor()
go bunchCacheJanitor()
go pubsubJanitor()
go sendAggregateData() go sendAggregateData()
go ircConnection() go ircConnection()