perf(ip-sync): avoid redundant client IP reads and writes (#6930)

The access-log scanner and the cross-node merge stored the same IP list in
opposite orders, so neither saw a row as unchanged, and the merge re-read
every preloaded row and re-upserted every attribution row each sync cycle.
All writers now share one canonical encoder (timestamp, then IP ascending),
the first CAS is seeded from the preload, and identical attribution rows are
skipped. A create race between the scanner and node sync now merges into the
winning row instead of dropping the loser's IPs, which on PostgreSQL also
aborted the scanner's whole scan transaction.

Closes #6927
This commit is contained in:
Hamed
2026-10-25 16:43:18 +03:30
committed by GitHub
parent 952c1c751a
commit 8eb58a4a14
22 changed files with 1273 additions and 247 deletions
@@ -0,0 +1,36 @@
package service
import (
"os"
"strings"
"testing"
)
func TestClientIpSyncPostgres(t *testing.T) {
if os.Getenv("XUI_DB_TYPE") != "postgres" || strings.TrimSpace(os.Getenv("XUI_DB_DSN")) == "" {
t.Skip("set XUI_DB_TYPE=postgres and XUI_DB_DSN to run PostgreSQL IP sync regressions")
}
for _, tc := range []struct {
name string
run func(*testing.T)
}{
{"seeded snapshot", TestClientIpSyncSeededSnapshot},
{"duplicates", TestClientIpSyncDuplicatePayloadsKeepUnion},
{"raw snapshot retry", TestClientIpSyncRawSnapshotAndSingleRetry},
{"create conflict", TestClientIpSyncCreateConflictMergesWinner},
{"exhaustion rollback", TestClientIpSyncCASExhaustionRollsBack},
{"concurrent writer", TestMergeInboundClientIps_RetriesAfterConcurrentWriter},
{"attribution unchanged", TestNodeClientIpCanonicalUnchangedSkipsUpsert},
{"remote ids", TestMergeInboundClientIps_CreatesNodeOnlyRowIgnoringRemoteId},
{"attribution round trip", TestRecordLocalClientIps_RoundTripByGuid},
{"attribution expiry", TestRecordLocalClientIps_MergesAndDropsStale},
{"attribution empty", TestUpsertNodeClientIps_EmptyMergeDeletesRow},
{"retention", TestPruneStaleClientIpsExpiresUnobservedRows},
{"cloned GUID", TestMergeClientIpsByGuid_RemapsClonedNodeSubtree},
{"maximum timestamps", TestMergeInboundClientIps_DedupKeepsMaxTimestamp},
{"stale merge", TestMergeInboundClientIps_DropsStaleIps},
{"stale insert", TestMergeInboundClientIps_SkipsAllStaleCreate},
} {
t.Run(tc.name, tc.run)
}
}