Files
headscale/hscontrol/state/maprequest_noop_test.go
Kristoffer Dalby 08f186f22a state: skip database persist for keepalive-only map requests
A lone LastSeen bump no longer triggers a full-row write and policy rescan.
2026-06-08 10:04:49 +02:00

75 lines
1.9 KiB
Go

package state
import (
"strings"
"sync/atomic"
"testing"
"github.com/stretchr/testify/require"
"gorm.io/gorm"
"tailscale.com/tailcfg"
)
// TestNoOpMapRequestSkipsPersist ensures an identical, no-op MapRequest does
// not issue a database UPDATE (nor the O(n) policy SetNodes scan that follows
// persistNodeToDB). The node state is unchanged, so persisting is pure waste on
// the hot map-request path.
func TestNoOpMapRequestSkipsPersist(t *testing.T) {
_, s, nodeID := persistTestSetup(t)
t.Cleanup(func() { _ = s.Close() })
var nodeUpdateCount atomic.Int64
gdb := s.DB().DB
cbName := "noop_count_node_updates"
err := gdb.Callback().Update().After("gorm:update").Register(cbName, func(tx *gorm.DB) {
if tx.Statement == nil {
return
}
if tx.Statement.Table == "nodes" ||
strings.Contains(strings.ToLower(tx.Statement.SQL.String()), "update \"nodes\"") {
nodeUpdateCount.Add(1)
}
})
require.NoError(t, err)
t.Cleanup(func() { _ = gdb.Callback().Update().Remove(cbName) })
nv, ok := s.GetNodeByID(nodeID)
require.True(t, ok, "node should exist in NodeStore")
stored := nv.AsStruct()
req := tailcfg.MapRequest{
NodeKey: stored.NodeKey,
DiscoKey: stored.DiscoKey,
Hostinfo: &tailcfg.Hostinfo{
Hostname: stored.Hostname,
NetInfo: &tailcfg.NetInfo{PreferredDERP: 1},
},
}
// First request establishes the Hostinfo/DERP state (expected to persist).
_, err = s.UpdateNodeFromMapRequest(nodeID, req)
require.NoError(t, err)
nodeUpdateCount.Store(0)
// Second request is value-identical: a no-op.
req2 := tailcfg.MapRequest{
NodeKey: stored.NodeKey,
DiscoKey: stored.DiscoKey,
Hostinfo: &tailcfg.Hostinfo{
Hostname: stored.Hostname,
NetInfo: &tailcfg.NetInfo{PreferredDERP: 1},
},
}
_, err = s.UpdateNodeFromMapRequest(nodeID, req2)
require.NoError(t, err)
require.Equalf(t, int64(0), nodeUpdateCount.Load(),
"no-op MapRequest should not issue any nodes-table UPDATE, got %d",
nodeUpdateCount.Load())
}