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:
parent
377afb7a6b
commit
d518759fa0
2 changed files with 81 additions and 4 deletions
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue