Sort FindDetectorMatches output for deterministic detector ordering

FindDetectorMatches builds its result from a map[DetectorKey]*DetectorMatch,
then iterates the map to build the output slice. Go map iteration is
intentionally randomized, so the returned detector order varied between runs.

This non-determinism affected result counts because the arrival order of
results at the notifier's 512-entry LRU dedup cache determines which entries
get evicted, leading to inconsistent deduplication across runs.

Sort the output by (detectorType, version, customDetectorName) so the
detector ordering is stable across runs.

Co-authored-by: Dylan Ayrey <[email protected]>
This commit is contained in:
Cursor Agent
2026-02-24 07:56:49 +00:00
co-authored by Dylan Ayrey
parent d4949d0c5a
commit 310c17fc20
+12
View File
@@ -2,6 +2,8 @@ package ahocorasick
import (
"bytes"
"cmp"
"slices"
"strings"
ahocorasick "github.com/BobuSumisu/aho-corasick"
@@ -281,6 +283,16 @@ func (ac *Core) FindDetectorMatches(chunkData []byte) []*DetectorMatch {
uniqueDetectors = append(uniqueDetectors, detectorMatch)
}
slices.SortFunc(uniqueDetectors, func(a, b *DetectorMatch) int {
if c := cmp.Compare(a.Key.detectorType, b.Key.detectorType); c != 0 {
return c
}
if c := cmp.Compare(a.Key.version, b.Key.version); c != 0 {
return c
}
return cmp.Compare(a.Key.customDetectorName, b.Key.customDetectorName)
})
return uniqueDetectors
}