diff --git a/agent/pkg/agent/agent_pool.go b/agent/pkg/agent/agent_pool.go index a22b8d31..594e1ad0 100644 --- a/agent/pkg/agent/agent_pool.go +++ b/agent/pkg/agent/agent_pool.go @@ -3,11 +3,11 @@ package agent import ( "iter" + "github.com/puzpuzpuz/xsync/v4" "github.com/yusing/go-proxy/internal/common" - "github.com/yusing/go-proxy/internal/utils/functional" ) -var agentPool = functional.NewMapOf[string, *AgentConfig]() +var agentPool = xsync.NewMap[string, *AgentConfig](xsync.WithPresize(10)) func init() { if common.IsTest { diff --git a/internal/homepage/list_icons.go b/internal/homepage/list_icons.go index b3f2ce1b..512d6edf 100644 --- a/internal/homepage/list_icons.go +++ b/internal/homepage/list_icons.go @@ -384,7 +384,8 @@ func UpdateSelfhstIcons() error { for _, item := range data { var tag string if item.Tags != "" { - tag = strutils.CommaSeperatedList(item.Tags)[0] + tag, _, _ = strings.Cut(item.Tags, ",") + tag = strings.TrimSpace(tag) } icon := &IconMeta{ DisplayName: item.Name, diff --git a/internal/net/gphttp/middleware/cidr_whitelist.go b/internal/net/gphttp/middleware/cidr_whitelist.go index 10da7a06..1a963632 100644 --- a/internal/net/gphttp/middleware/cidr_whitelist.go +++ b/internal/net/gphttp/middleware/cidr_whitelist.go @@ -5,16 +5,16 @@ import ( "net/http" "github.com/go-playground/validator/v10" + "github.com/puzpuzpuz/xsync/v4" gphttp "github.com/yusing/go-proxy/internal/net/gphttp" nettypes "github.com/yusing/go-proxy/internal/net/types" "github.com/yusing/go-proxy/internal/serialization" - F "github.com/yusing/go-proxy/internal/utils/functional" ) type ( cidrWhitelist struct { CIDRWhitelistOpts - cachedAddr F.Map[string, bool] // cache for trusted IPs + cachedAddr *xsync.Map[string, bool] // cache for trusted IPs } CIDRWhitelistOpts struct { Allow []*nettypes.CIDR `validate:"min=1"` @@ -42,7 +42,7 @@ func init() { // setup implements MiddlewareWithSetup. func (wl *cidrWhitelist) setup() { wl.CIDRWhitelistOpts = cidrWhitelistDefaults - wl.cachedAddr = F.NewMapOf[string, bool]() + wl.cachedAddr = xsync.NewMap[string, bool](xsync.WithPresize(100)) } // before implements RequestModifier. diff --git a/internal/net/gphttp/middleware/errorpage/error_page.go b/internal/net/gphttp/middleware/errorpage/error_page.go index e63b65a3..ff002810 100644 --- a/internal/net/gphttp/middleware/errorpage/error_page.go +++ b/internal/net/gphttp/middleware/errorpage/error_page.go @@ -6,12 +6,12 @@ import ( "path" "sync" + "github.com/puzpuzpuz/xsync/v4" "github.com/rs/zerolog/log" "github.com/yusing/go-proxy/internal/common" "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/task" U "github.com/yusing/go-proxy/internal/utils" - F "github.com/yusing/go-proxy/internal/utils/functional" W "github.com/yusing/go-proxy/internal/watcher" "github.com/yusing/go-proxy/internal/watcher/events" ) @@ -21,7 +21,7 @@ const errPagesBasePath = common.ErrorPagesBasePath var ( setupOnce sync.Once dirWatcher W.Watcher - fileContentMap = F.NewMapOf[string, []byte]() + fileContentMap = xsync.NewMap[string, []byte](xsync.WithGrowOnly()) ) func setup() { @@ -52,7 +52,7 @@ func loadContent() { return } for _, file := range files { - if fileContentMap.Has(file) { + if _, ok := fileContentMap.Load(file); ok { continue } content, err := os.ReadFile(file) diff --git a/internal/serialization/serialization.go b/internal/serialization/serialization.go index 25971984..739f99e2 100644 --- a/internal/serialization/serialization.go +++ b/internal/serialization/serialization.go @@ -14,7 +14,6 @@ import ( "github.com/puzpuzpuz/xsync/v4" "github.com/yusing/go-proxy/internal/gperr" "github.com/yusing/go-proxy/internal/utils" - "github.com/yusing/go-proxy/internal/utils/functional" "github.com/yusing/go-proxy/internal/utils/strutils" ) @@ -536,7 +535,7 @@ func UnmarshalValidateYAMLIntercept[T any](data []byte, target *T, intercept fun return MapUnmarshalValidate(m, target) } -func UnmarshalValidateYAMLXSync[V any](data []byte) (_ functional.Map[string, V], err gperr.Error) { +func UnmarshalValidateYAMLXSync[V any](data []byte) (_ *xsync.Map[string, V], err gperr.Error) { m := make(map[string]any) if err = gperr.Wrap(yaml.Unmarshal(data, &m)); err != nil { return @@ -545,7 +544,11 @@ func UnmarshalValidateYAMLXSync[V any](data []byte) (_ functional.Map[string, V] if err = MapUnmarshalValidate(m, m2); err != nil { return } - return functional.NewMapFrom(m2), nil + ret := xsync.NewMap[string, V](xsync.WithPresize(len(m))) + for k, v := range m2 { + ret.Store(k, v) + } + return ret, nil } func loadSerialized[T any](path string, dst *T, deserialize func(data []byte, dst any) error) error { diff --git a/internal/utils/functional/map.go b/internal/utils/functional/map.go deleted file mode 100644 index bbc355a6..00000000 --- a/internal/utils/functional/map.go +++ /dev/null @@ -1,103 +0,0 @@ -package functional - -import ( - "sync" - - "github.com/goccy/go-yaml" - "github.com/puzpuzpuz/xsync/v4" -) - -type Map[KT comparable, VT any] struct { - *xsync.Map[KT, VT] -} - -const minParallelSize = 4 - -func NewMapOf[KT comparable, VT any](options ...func(*xsync.MapConfig)) Map[KT, VT] { - return Map[KT, VT]{xsync.NewMap[KT, VT](options...)} -} - -func NewMapFrom[KT comparable, VT any](m map[KT]VT) (res Map[KT, VT]) { - res = NewMapOf[KT, VT](xsync.WithPresize(len(m))) - for k, v := range m { - res.Store(k, v) - } - return -} - -func NewMap[MapType Map[KT, VT], KT comparable, VT any]() Map[KT, VT] { - return NewMapOf[KT, VT]() -} - -// RangeAll calls the given function for each key-value pair in the map. -// -// Parameters: -// -// do: function to call for each key-value pair -// -// Returns: -// -// nothing -func (m Map[KT, VT]) RangeAll(do func(k KT, v VT)) { - m.Range(func(k KT, v VT) bool { - do(k, v) - return true - }) -} - -// RangeAllParallel calls the given function for each key-value pair in the map, -// in parallel. The map is not safe for modification from within the function. -// -// Parameters: -// -// do: function to call for each key-value pair -// -// Returns: -// -// nothing -func (m Map[KT, VT]) RangeAllParallel(do func(k KT, v VT)) { - if m.Size() < minParallelSize { - m.RangeAll(do) - return - } - - var wg sync.WaitGroup - for k, v := range m.Range { - wg.Add(1) - go func(k KT, v VT) { - defer wg.Done() - do(k, v) - }(k, v) - } - wg.Wait() -} - -// CollectErrors calls the given function for each key-value pair in the map, -// then returns a slice of errors collected. -func (m Map[KT, VT]) CollectErrors(do func(k KT, v VT) error) []error { - errs := make([]error, 0) - m.Range(func(k KT, v VT) bool { - if err := do(k, v); err != nil { - errs = append(errs, err) - } - return true - }) - return errs -} - -func (m Map[KT, VT]) Has(k KT) bool { - _, ok := m.Load(k) - return ok -} - -func (m Map[KT, VT]) String() string { - tmp := make(map[KT]VT, m.Size()) - m.RangeAll(func(k KT, v VT) { - tmp[k] = v - }) - data, err := yaml.Marshal(&tmp) - if err != nil { - return err.Error() - } - return string(data) -} diff --git a/internal/utils/functional/map_test.go b/internal/utils/functional/map_test.go deleted file mode 100644 index 97152101..00000000 --- a/internal/utils/functional/map_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package functional_test - -import ( - "testing" - - . "github.com/yusing/go-proxy/internal/utils/functional" - . "github.com/yusing/go-proxy/internal/utils/testing" -) - -func TestNewMapFrom(t *testing.T) { - m := NewMapFrom(map[string]int{ - "a": 1, - "b": 2, - "c": 3, - }) - ExpectEqual(t, m.Size(), 3) - ExpectTrue(t, m.Has("a")) - ExpectTrue(t, m.Has("b")) - ExpectTrue(t, m.Has("c")) -} diff --git a/internal/utils/go.mod b/internal/utils/go.mod index 8eeb0af6..dddfec00 100644 --- a/internal/utils/go.mod +++ b/internal/utils/go.mod @@ -3,7 +3,6 @@ module github.com/yusing/go-proxy/internal/utils go 1.25.0 require ( - github.com/goccy/go-yaml v1.18.0 github.com/puzpuzpuz/xsync/v4 v4.1.0 github.com/rs/zerolog v1.34.0 github.com/stretchr/testify v1.11.1 diff --git a/internal/utils/go.sum b/internal/utils/go.sum index b8eea3ab..6ece7247 100644 --- a/internal/utils/go.sum +++ b/internal/utils/go.sum @@ -1,8 +1,6 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= -github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= diff --git a/internal/watcher/health/monitor/last_seen.go b/internal/watcher/health/monitor/last_seen.go index 36e7cebc..f7c80be6 100644 --- a/internal/watcher/health/monitor/last_seen.go +++ b/internal/watcher/health/monitor/last_seen.go @@ -3,10 +3,10 @@ package monitor import ( "time" - F "github.com/yusing/go-proxy/internal/utils/functional" + "github.com/puzpuzpuz/xsync/v4" ) -var lastSeenMap = F.NewMapOf[string, time.Time]() +var lastSeenMap = xsync.NewMap[string, time.Time](xsync.WithPresize(50), xsync.WithGrowOnly()) func SetLastSeen(service string, lastSeen time.Time) { lastSeenMap.Store(service, lastSeen)