fix(nftables): clean counter state on forward delete

This commit is contained in:
sagitchu
2026-06-06 22:40:57 +08:00
committed by sagit
parent 006ea97200
commit 7ab0db29ae
2 changed files with 47 additions and 0 deletions
@@ -769,6 +769,9 @@ func (r *Repository) DeleteForwardCascade(forwardID int64) error {
return errors.New("repository not initialized")
}
return r.db.Transaction(func(tx *gorm.DB) error {
if err := tx.Where("forward_id = ?", forwardID).Delete(&model.NftCounterState{}).Error; err != nil {
return err
}
if err := tx.Where("forward_id = ?", forwardID).Delete(&model.ForwardPort{}).Error; err != nil {
return err
}
@@ -5,6 +5,8 @@ import (
"path/filepath"
"testing"
"time"
"go-backend/internal/store/model"
)
func TestNftCounterStateUpsertUpdatesExistingKey(t *testing.T) {
@@ -107,6 +109,48 @@ func TestNftCounterStateDeleteByForwardRemovesOnlyMatchingRows(t *testing.T) {
}
}
func TestDeleteForwardCascadeRemovesNftCounterStateOnlyForDeletedForward(t *testing.T) {
r, err := Open(":memory:")
if err != nil {
t.Fatalf("open repo: %v", err)
}
defer r.Close()
now := time.Now().UnixMilli()
forwards := []model.Forward{
{ID: 42, UserID: 1, UserName: "admin", Name: "forward-a", TunnelID: 10, RemoteAddr: "203.0.113.1:80", Strategy: "fifo", CreatedTime: now, UpdatedTime: now, Status: 1},
{ID: 43, UserID: 1, UserName: "admin", Name: "forward-b", TunnelID: 10, RemoteAddr: "203.0.113.2:80", Strategy: "fifo", CreatedTime: now, UpdatedTime: now, Status: 1},
}
if err := r.DB().Create(&forwards).Error; err != nil {
t.Fatalf("seed forwards: %v", err)
}
if err := r.UpsertNftCounterStates([]NftCounterStateInput{
{NodeID: 11, ForwardID: 42, Protocol: "tcp", Direction: "to-target", RuleHash: "a", Bytes: 100, Packets: 10, CollectedTime: now},
{NodeID: 11, ForwardID: 43, Protocol: "udp", Direction: "from-target", RuleHash: "b", Bytes: 200, Packets: 20, CollectedTime: now},
}, now); err != nil {
t.Fatalf("UpsertNftCounterStates: %v", err)
}
if err := r.DeleteForwardCascade(42); err != nil {
t.Fatalf("DeleteForwardCascade: %v", err)
}
rows, err := r.GetNftCounterStatesByNode(11)
if err != nil {
t.Fatalf("GetNftCounterStatesByNode: %v", err)
}
if len(rows) != 1 || rows[0].ForwardID != 43 {
t.Fatalf("expected only forward 43 counter state to remain, got %+v", rows)
}
var deletedForwardCount int64
if err := r.DB().Model(&model.Forward{}).Where("id = ?", int64(42)).Count(&deletedForwardCount).Error; err != nil {
t.Fatalf("count deleted forward: %v", err)
}
if deletedForwardCount != 0 {
t.Fatalf("expected forward 42 deleted, count=%d", deletedForwardCount)
}
}
func TestNftCounterStateUpsertSkipsInvalidProtocolAndDirection(t *testing.T) {
r, err := Open(":memory:")
if err != nil {