Closed pravus closed 3 years ago
Awesome bug report! I have completely removed LFUImmutable cache and replaced it with a way simpler cache system, as the default. The new cache has +70% test coverage and can be found in the develop branch. I'm going to make a release right now, but be aware it's a breaking upgrade.
Made a release. Feel free to ask any questions if you have migration issues.
@pravus just a checkup, did this change work for you?
Hi, @andersfylling.
Yes it does appear to be working. I bumped the version on my project to the new release and the problem I was seeing is now gone. I know you said it was a potentially breaking release but I didn't have to change anything other than the version of this module. Thanks for getting this out so quickly!
Describe the bug It appears as though the default LFUImmutable Cache driver uses multiple locks when performing a channel update and will block the event queue causing heartbeat events to be missed and eventually a reconnect loop similar to the issue described here: https://github.com/andersfylling/disgord/issues/390
Expected behavior It is expected that LFUImmutable cache updates should never block the event queue and allow received events from Discord to be processed normally.
Error messages Similar to the issue stated above, here are log messages from Disgord when I was able to detect the lock condition:
Desktop (please complete the following information):
Additional context I was able to debug this by adding tracing statements to various parts of the client. It looks like what happens is that Discord sends a
CHANNEL_UPDATE
packet which passes throughoperationHandlers()
ininternal/gateway/client.go
which will then callonDiscordEvent()
ininternal/gateway/eventclient.go
via the action dispatch. This method sends anEvent
struct viac.eventChan
which is read by thedemultiplexer()
method inreactor.go
. Once an event is read it will be passed tocacheDispatcher()
which will invoke the appropriate type-handler for the event on theCache
implementation.In the
ChannelUpdate()
method defined forCacheLFUImmutable
there is a closure namedupdateChannel
which creates a new mutex onc.Channels
for a given channel ID. If the channel already exists in the cache this will cause a deadlock because another lock is obtained before calling the closure.I have found two workarounds for this:
1) Specify a
CacheNop
struct as theCache
handler when constructing a client instance.2) Remove the mutex from the
updateChannel
closure inChannelUpdate()
in theCacheLFUImmutable
implementation. While this change fixes my specific issue I am unsure if it is a proper solution.