diff --git a/server/jetstream_cluster.go b/server/jetstream_cluster.go index 387c1dab077..adc0cdf7e38 100644 --- a/server/jetstream_cluster.go +++ b/server/jetstream_cluster.go @@ -1225,6 +1225,8 @@ func (js *jetStream) monitorCluster() { doSnapshot() return case <-rqch: + // Clean signal from shutdown routine so do best effort attempt to snapshot meta layer. + doSnapshot() return case <-qch: // Clean signal from shutdown routine so do best effort attempt to snapshot meta layer. diff --git a/server/raft.go b/server/raft.go index 78c6a1cb9c1..cf2812a5c65 100644 --- a/server/raft.go +++ b/server/raft.go @@ -1958,7 +1958,7 @@ func (n *raft) run() { n.apply.push(nil) runner: - for s.isRunning() { + for { switch n.State() { case Follower: n.runAsFollower() diff --git a/server/raft_test.go b/server/raft_test.go index 54b133be32b..76cc2512348 100644 --- a/server/raft_test.go +++ b/server/raft_test.go @@ -2773,6 +2773,35 @@ func TestNRGSnapshotRecovery(t *testing.T) { require_Equal(t, n.applied, 0) } +func TestNRGKeepRunningOnServerShutdown(t *testing.T) { + n, cleanup := initSingleMemRaftNode(t) + defer cleanup() + + n.RLock() + s := n.s + wal := n.wal.(*memStore) + n.RUnlock() + + n.wg.Add(1) + s.startGoRoutine(n.run, nil) + + s.running.Store(false) + time.Sleep(time.Second) + + wal.mu.RLock() + msgs := wal.msgs + wal.mu.RUnlock() + require_NotNil(t, msgs) + + n.Stop() + n.WaitForStop() + + wal.mu.RLock() + msgs = wal.msgs + wal.mu.RUnlock() + require_True(t, msgs == nil) +} + // This is a RaftChainOfBlocks test where a block is proposed and then we wait for all replicas to apply it before // proposing the next one. // The test may fail if: