Skip to content

Commit 5cb8b31

Browse files
committed
reset LastMissedHeartbeatIndex to zero when node is ready
1 parent bb0aa13 commit 5cb8b31

File tree

3 files changed

+103
-3
lines changed

3 files changed

+103
-3
lines changed

nomad/state/state_store.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -1044,9 +1044,13 @@ func (s *StateStore) updateNodeStatusTxn(txn *txn, nodeID, status string, update
10441044
copyNode.Status = status
10451045
copyNode.ModifyIndex = txn.Index
10461046

1047-
// Update last missed heartbeat if the node became unresponsive.
1047+
// Update last missed heartbeat if the node became unresponsive or reset it
1048+
// zero if the node became ready.
10481049
if !existingNode.UnresponsiveStatus() && copyNode.UnresponsiveStatus() {
10491050
copyNode.LastMissedHeartbeatIndex = txn.Index
1051+
} else if existingNode.Status != structs.NodeStatusReady &&
1052+
copyNode.Status == structs.NodeStatusReady {
1053+
copyNode.LastMissedHeartbeatIndex = 0
10501054
}
10511055

10521056
// Insert the node

nomad/state/state_store_test.go

+96
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,102 @@ func TestStateStore_UpdateNodeStatus_Node(t *testing.T) {
13551355
require.False(watchFired(ws))
13561356
}
13571357

1358+
func TestStatStore_UpdateNodeStatus_LastMissedHeartbeatIndex(t *testing.T) {
1359+
ci.Parallel(t)
1360+
1361+
testCases := []struct {
1362+
name string
1363+
transitions []string
1364+
expectedIndexes []uint64
1365+
}{
1366+
{
1367+
name: "disconnect",
1368+
transitions: []string{
1369+
structs.NodeStatusReady,
1370+
structs.NodeStatusDisconnected,
1371+
},
1372+
expectedIndexes: []uint64{0, 1001},
1373+
},
1374+
{
1375+
name: "reconnect",
1376+
transitions: []string{
1377+
structs.NodeStatusReady,
1378+
structs.NodeStatusDisconnected,
1379+
structs.NodeStatusInit,
1380+
structs.NodeStatusReady,
1381+
},
1382+
expectedIndexes: []uint64{0, 1001, 1001, 0},
1383+
},
1384+
{
1385+
name: "down",
1386+
transitions: []string{
1387+
structs.NodeStatusReady,
1388+
structs.NodeStatusDown,
1389+
},
1390+
expectedIndexes: []uint64{0, 1001},
1391+
},
1392+
{
1393+
name: "multiple reconnects",
1394+
transitions: []string{
1395+
structs.NodeStatusReady,
1396+
structs.NodeStatusDisconnected,
1397+
structs.NodeStatusInit,
1398+
structs.NodeStatusReady,
1399+
structs.NodeStatusDown,
1400+
structs.NodeStatusReady,
1401+
structs.NodeStatusDisconnected,
1402+
structs.NodeStatusInit,
1403+
structs.NodeStatusReady,
1404+
},
1405+
expectedIndexes: []uint64{0, 1001, 1001, 0, 1004, 0, 1006, 1006, 0},
1406+
},
1407+
{
1408+
name: "multiple heartbeats",
1409+
transitions: []string{
1410+
structs.NodeStatusReady,
1411+
structs.NodeStatusDisconnected,
1412+
structs.NodeStatusInit,
1413+
structs.NodeStatusReady,
1414+
structs.NodeStatusReady,
1415+
structs.NodeStatusReady,
1416+
},
1417+
expectedIndexes: []uint64{0, 1001, 1001, 0, 0, 0},
1418+
},
1419+
{
1420+
name: "delayed alloc update",
1421+
transitions: []string{
1422+
structs.NodeStatusReady,
1423+
structs.NodeStatusDisconnected,
1424+
structs.NodeStatusInit,
1425+
structs.NodeStatusInit,
1426+
structs.NodeStatusInit,
1427+
structs.NodeStatusReady,
1428+
},
1429+
expectedIndexes: []uint64{0, 1001, 1001, 1001, 1001, 0},
1430+
},
1431+
}
1432+
1433+
for _, tc := range testCases {
1434+
t.Run(tc.name, func(t *testing.T) {
1435+
state := testStateStore(t)
1436+
node := mock.Node()
1437+
must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 999, node))
1438+
1439+
for i, status := range tc.transitions {
1440+
now := time.Now().UnixNano()
1441+
err := state.UpdateNodeStatus(structs.MsgTypeTestSetup, uint64(1000+i), node.ID, status, now, nil)
1442+
must.NoError(t, err)
1443+
1444+
ws := memdb.NewWatchSet()
1445+
out, err := state.NodeByID(ws, node.ID)
1446+
must.NoError(t, err)
1447+
must.Eq(t, tc.expectedIndexes[i], out.LastMissedHeartbeatIndex)
1448+
must.Eq(t, status, out.Status)
1449+
}
1450+
})
1451+
}
1452+
}
1453+
13581454
func TestStateStore_BatchUpdateNodeDrain(t *testing.T) {
13591455
ci.Parallel(t)
13601456
require := require.New(t)

nomad/structs/structs.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -2090,8 +2090,8 @@ type Node struct {
20902090
// LastDrain contains metadata about the most recent drain operation
20912091
LastDrain *DrainMetadata
20922092

2093-
// LastMissedHeartbeatIndex stores the Raft index when the node
2094-
// last missed a heartbeat.
2093+
// LastMissedHeartbeatIndex stores the Raft index when the node last missed
2094+
// a heartbeat. It resets to zero once the node is marked as ready again.
20952095
LastMissedHeartbeatIndex uint64
20962096

20972097
// LastAllocUpdateIndex stores the Raft index of the last time the node

0 commit comments

Comments
 (0)