Fixed SegmentedQueues not being cleaned up on session purge#833
Fixed SegmentedQueues not being cleaned up on session purge#833andsel merged 3 commits intomoquette-io:mainfrom
Conversation
| void remove(String clientID) { | ||
| final Session old = pool.remove(clientID); | ||
| if (old != null) { | ||
| unsubscribe(old); |
There was a problem hiding this comment.
Are we sure that pool's session is the same instance of current session?
There was a problem hiding this comment.
The only situation where it could happen that there are two sessions with the same clientID is when a client re-connects with cleanSession=true. In that case the old session is purged before the new session is created.
I can change the code to only remove from the pool if the session is the same as the one in the pool.
That just lead me to a different potential issue, with the sessionExpirationService timer. I think that timer could trigger right as a client is reconnecting, and as it is based on the clientID, it could kill a session that was just made. Shouldn't removeExpiredSession check if the session really is expired, and not reconnected? And probably do the cleanup on the session thread?
There was a problem hiding this comment.
I think that timer could trigger right as a client is reconnecting, and as it is based on the clientID, it could kill a session that was just made. Shouldn't removeExpiredSession check if the session really is expired, and not reconnected? And probably do the cleanup on the session thread?
Why do you think that that case could happen? Looking at the code, when a session disconnect it's also untracked from the session expiration service. When it reconnects it's tracked again, reinserting the reference into the pool managed by the session expiration service.
In this way all session tracked by the expiration service are session present in the session registry, and so can't be the case of a duplication.
There was a problem hiding this comment.
The session expiration service only contains disconnected sessions that have cleanSession=false. Sessions that are connected don't need to be tracked since they can't expire, and sessions with cleanSession=true are cleaned up on disconnect.
Imagine a disconnected session with cleanSession=false. The expiration service finds it in the queue and removes it for cleaning, but there is a time interval between it being removed from the queue and it being actually cleaned. Either because there is a large batch of sessions to expire, or because the thread is put in hold. In that time the user reconnects, and a new session is made that inherits the subscriptions and clientID of the old session. Now the expiration thread is reactivated and kills the thread with the stored clientID...
There was a problem hiding this comment.
@hylkevds you are right! Very good explanation of the case. I think this aspect should be kept out of this PR, and an issue tracking the problem should opened so be solved. Thanks for pointing it out 👍
I'll look into making some tests for this. |
c22869c to
c20f3c5
Compare
c20f3c5 to
9acaf3a
Compare
|
@andsel: I added a test to verify the queue cleanup and page-file re-use. |
| segmentsAllocationLock.lock(); | ||
| try { | ||
| while (segmentRef != null) { | ||
| LOG.debug("Consumed tail segment {} from queue {}", segmentRef, queueName); |
There was a problem hiding this comment.
Would rewrite this log as
| LOG.debug("Consumed tail segment {} from queue {}", segmentRef, queueName); | |
| LOG.debug("Purging segment {} from queue {}", segmentRef, queueName); |
There was a problem hiding this comment.
No problem, I added both logging lines.
d88b42f to
e776a3a
Compare
andsel
left a comment
There was a problem hiding this comment.
Please keep this PR with only changes related to the persistent queues, that would help a lot the review and the change history of the project.
Please create a follow up PR for the issue related to session management.
| void remove(String clientID) { | ||
| final Session old = pool.remove(clientID); | ||
| if (old != null) { | ||
| void remove(Session session) { |
There was a problem hiding this comment.
I would keep the fixes for session management out of this PR, so that's more clear what this PR does and simplify to understand the change history, reducing the scope of the PR
There was a problem hiding this comment.
I've split the commit containing the SessionRegistry changes into a separate branch. PR coming soon...
e776a3a to
a1d9cc4
Compare
Segmented queues were closed, but not cleared on session close. This resulted in segments not being returned to the pool, and thus disk-space not being released. The queues were also not removed from the QueuePool, resulting in a memory leak.
a1d9cc4 to
0c8e934
Compare
|
Thanks @hylkevds for your contribution to the project! |
Segmented queues were closed, but not cleared on session close. This resulted in segments not being returned to the pool, and thus disk-space not being released. The queues were also not removed from the QueuePool, resulting in a memory leak.
Relates #734