From d0213bfd4f247729ebcb1a9ff37ab92865ce02eb Mon Sep 17 00:00:00 2001 From: Konstantin Dudkov Date: Thu, 23 May 2024 12:11:46 +0300 Subject: [PATCH] utils --- cmd/goatak_server/admin_api.go | 4 +- cmd/goatak_server/main.go | 10 +- cmd/mm/api.go | 2 +- cmd/webclient/api.go | 2 +- cmd/webclient/http_server.go | 6 +- cmd/webclient/main.go | 14 +-- go.mod | 5 +- go.sum | 10 +- internal/callbacks/callbacks_test.go | 52 --------- internal/callbacks/events.go | 66 ----------- internal/callbacks/manager.go | 45 -------- internal/client/enroll.go | 2 +- pkg/request/request.go | 158 --------------------------- 13 files changed, 29 insertions(+), 347 deletions(-) delete mode 100644 internal/callbacks/callbacks_test.go delete mode 100644 internal/callbacks/events.go delete mode 100644 internal/callbacks/manager.go delete mode 100644 pkg/request/request.go diff --git a/cmd/goatak_server/admin_api.go b/cmd/goatak_server/admin_api.go index 35453f1e..918b6d66 100644 --- a/cmd/goatak_server/admin_api.go +++ b/cmd/goatak_server/admin_api.go @@ -353,8 +353,8 @@ func getWsHandler(app *App) air.Handler { h := wshandler.NewHandler(name, ws) app.logger.Debug("ws listener connected") - app.changeCb.Subscribe(name, h.SendItem) - app.deleteCb.Subscribe(name, h.DeleteItem) + app.changeCb.SubscribeNamed(name, h.SendItem) + app.deleteCb.SubscribeNamed(name, h.DeleteItem) h.Listen() app.logger.Debug("ws listener disconnected") diff --git a/cmd/goatak_server/main.go b/cmd/goatak_server/main.go index 6d00fdb9..5bdfa63f 100644 --- a/cmd/goatak_server/main.go +++ b/cmd/goatak_server/main.go @@ -20,6 +20,7 @@ import ( "github.com/glebarez/sqlite" "github.com/google/uuid" + "github.com/kdudkov/goutils/callback" "github.com/prometheus/client_golang/prometheus" "github.com/spf13/viper" "gorm.io/gorm" @@ -27,7 +28,6 @@ import ( "software.sslmate.com/src/go-pkcs12" "github.com/kdudkov/goatak/cmd/goatak_server/missions" - "github.com/kdudkov/goatak/internal/callbacks" "github.com/kdudkov/goatak/internal/client" im "github.com/kdudkov/goatak/internal/model" "github.com/kdudkov/goatak/internal/pm" @@ -84,8 +84,8 @@ type App struct { handlers sync.Map - changeCb *callbacks.Callback[*model.Item] - deleteCb *callbacks.Callback[string] + changeCb *callback.Callback[*model.Item] + deleteCb *callback.Callback[string] items repository.ItemsRepository messages []*model.ChatMessage @@ -107,8 +107,8 @@ func NewApp(config *AppConfig) *App { users: repository.NewFileUserRepo(config.usersFile), ch: make(chan *cot.CotMessage, 100), handlers: sync.Map{}, - changeCb: callbacks.New[*model.Item](), - deleteCb: callbacks.New[string](), + changeCb: callback.New[*model.Item](), + deleteCb: callback.New[string](), items: repository.NewItemsMemoryRepo(), feeds: repository.NewFeedsFileRepo(filepath.Join(config.dataDir, "feeds")), uid: uuid.NewString(), diff --git a/cmd/mm/api.go b/cmd/mm/api.go index 04118a37..fa0c8ea6 100644 --- a/cmd/mm/api.go +++ b/cmd/mm/api.go @@ -10,7 +10,7 @@ import ( "net/http" "time" - "github.com/kdudkov/goatak/pkg/request" + "github.com/kdudkov/goutils/request" mp "github.com/kdudkov/goatak/internal/model" "github.com/kdudkov/goatak/pkg/model" diff --git a/cmd/webclient/api.go b/cmd/webclient/api.go index d2f7bf0d..6af9f606 100644 --- a/cmd/webclient/api.go +++ b/cmd/webclient/api.go @@ -8,7 +8,7 @@ import ( "net/http" "time" - "github.com/kdudkov/goatak/pkg/request" + "github.com/kdudkov/goutils/request" "github.com/kdudkov/goatak/pkg/model" ) diff --git a/cmd/webclient/http_server.go b/cmd/webclient/http_server.go index 29337761..c58bffe0 100644 --- a/cmd/webclient/http_server.go +++ b/cmd/webclient/http_server.go @@ -247,9 +247,9 @@ func getWsHandler(app *App) air.Handler { h := wshandler.NewHandler(name, ws) app.logger.Debug("ws listener connected") - app.changeCb.Subscribe(name, h.SendItem) - app.deleteCb.Subscribe(name, h.DeleteItem) - app.chatCb.Subscribe(name, h.NewChatMessage) + app.changeCb.SubscribeNamed(name, h.SendItem) + app.deleteCb.SubscribeNamed(name, h.DeleteItem) + app.chatCb.SubscribeNamed(name, h.NewChatMessage) h.Listen() app.logger.Debug("ws listener disconnected") diff --git a/cmd/webclient/main.go b/cmd/webclient/main.go index f77d5af6..0d29342f 100644 --- a/cmd/webclient/main.go +++ b/cmd/webclient/main.go @@ -22,7 +22,6 @@ import ( "github.com/spf13/viper" - "github.com/kdudkov/goatak/internal/callbacks" "github.com/kdudkov/goatak/internal/client" "github.com/kdudkov/goatak/internal/repository" "github.com/kdudkov/goatak/pkg/cot" @@ -30,6 +29,7 @@ import ( "github.com/kdudkov/goatak/pkg/log" "github.com/kdudkov/goatak/pkg/model" "github.com/kdudkov/goatak/pkg/tlsutil" + "github.com/kdudkov/goutils/callback" ) const ( @@ -51,9 +51,9 @@ type App struct { tlsCert *tls.Certificate cas *x509.CertPool cl *client.ConnClientHandler - changeCb *callbacks.Callback[*model.Item] - deleteCb *callbacks.Callback[string] - chatCb *callbacks.Callback[*model.ChatMessage] + changeCb *callback.Callback[*model.Item] + deleteCb *callback.Callback[string] + chatCb *callback.Callback[*model.ChatMessage] eventProcessors []*EventProcessor remoteAPI *RemoteAPI saveFile string @@ -105,9 +105,9 @@ func NewApp(uid string, callsign string, connectStr string, webPort int) *App { webPort: webPort, items: repository.NewItemsMemoryRepo(), dialTimeout: time.Second * 5, - changeCb: callbacks.New[*model.Item](), - deleteCb: callbacks.New[string](), - chatCb: callbacks.New[*model.ChatMessage](), + changeCb: callback.New[*model.Item](), + deleteCb: callback.New[string](), + chatCb: callback.New[*model.ChatMessage](), chatMessages: model.NewChatMessages(uid), eventProcessors: make([]*EventProcessor, 0), pos: atomic.Pointer[model.Pos]{}, diff --git a/go.mod b/go.mod index b2bca926..810a8755 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/kdudkov/goatak -go 1.21 +go 1.22.2 require ( github.com/air-gases/authenticator v0.11.0 @@ -9,11 +9,11 @@ require ( github.com/glebarez/sqlite v1.11.0 github.com/google/uuid v1.6.0 github.com/jroimartin/gocui v0.5.0 + github.com/kdudkov/goutils v0.0.0-20240523090608-c589e6c759b7 github.com/prometheus/client_golang v1.19.0 github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.9.0 golang.org/x/crypto v0.22.0 - golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f golang.org/x/net v0.24.0 google.golang.org/protobuf v1.33.0 gopkg.in/yaml.v3 v3.0.1 @@ -60,6 +60,7 @@ require ( github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 8aa0260e..29afafff 100644 --- a/go.sum +++ b/go.sum @@ -56,6 +56,8 @@ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jroimartin/gocui v0.5.0 h1:DCZc97zY9dMnHXJSJLLmx9VqiEnAj0yh0eTNpuEtG/4= github.com/jroimartin/gocui v0.5.0/go.mod h1:l7Hz8DoYoL6NoYnlnaX6XCNR62G7J5FfSW5jEogzaxE= +github.com/kdudkov/goutils v0.0.0-20240523090608-c589e6c759b7 h1:Ff0x/5mSsHrHiZOyECj3FQE1a9reGF5YqqckLrJn+/U= +github.com/kdudkov/goutils v0.0.0-20240523090608-c589e6c759b7/go.mod h1:43RRUp5UXgq5CkCpw7thT4W4VYeMydShe6T0eart6Js= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -150,8 +152,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= -golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -175,8 +177,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= -golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= +golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= diff --git a/internal/callbacks/callbacks_test.go b/internal/callbacks/callbacks_test.go deleted file mode 100644 index c314cd0d..00000000 --- a/internal/callbacks/callbacks_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package callbacks - -import ( - "context" - "fmt" - "sync" - "testing" - "time" - - "golang.org/x/exp/rand" -) - -func TestRemove(t *testing.T) { - cb := New[string]() - - for i := 0; i < 30; i++ { - cb.Add(func(msg string) bool { - if rand.Intn(1000) == 1 { - fmt.Printf("remove\n") - return false - } - - return true - }) - } - - n := 10 - - ctx, cancel := context.WithCancel(context.Background()) - - wg := new(sync.WaitGroup) - - for i := 0; i < n; i++ { - wg.Add(1) - - go func() { - for ctx.Err() == nil { - cb.AddMessage("aaa") - - time.Sleep(time.Millisecond * time.Duration(rand.Intn(100))) - } - - wg.Done() - }() - } - - time.Sleep(time.Second * 5) - cancel() - - wg.Wait() - -} diff --git a/internal/callbacks/events.go b/internal/callbacks/events.go deleted file mode 100644 index afbf51fb..00000000 --- a/internal/callbacks/events.go +++ /dev/null @@ -1,66 +0,0 @@ -package callbacks - -import ( - "sync" - - "github.com/google/uuid" -) - -type Events struct { - cb sync.Map -} - -type EventHandler struct { - cb sync.Map -} - -func NewEvents() *Events { - return &Events{cb: sync.Map{}} -} - -func (e *Events) On(key string, f func(data any) bool) { - if k, ok := e.cb.Load(key); !ok { - eh := &EventHandler{cb: sync.Map{}} - k1, _ := e.cb.LoadOrStore(key, eh) - - if eh1, ok := k1.(*EventHandler); ok { - eh1.add(f) - } - } else { - if eh, ok := k.(*EventHandler); ok { - eh.add(f) - } - } -} - -func (e *Events) Add(key string, data any) { - if k, ok := e.cb.Load(key); ok { - if eh, ok := k.(*EventHandler); ok { - eh.fire(data) - } - } -} - -func (eh *EventHandler) fire(data any) { - eh.cb.Range(func(key, value any) bool { - if fn, ok := value.(func(data any) bool); ok { - go func() { - if !fn(data) { - eh.remove(key.(string)) - } - }() - } - - return true - }) -} - -func (eh *EventHandler) add(fn func(data any) bool) { - eh.cb.Store(uuid.NewString(), fn) -} - -func (eh *EventHandler) remove(name string) bool { - _, found := eh.cb.LoadAndDelete(name) - - return found -} diff --git a/internal/callbacks/manager.go b/internal/callbacks/manager.go deleted file mode 100644 index 507c8045..00000000 --- a/internal/callbacks/manager.go +++ /dev/null @@ -1,45 +0,0 @@ -package callbacks - -import ( - "sync" - - "github.com/google/uuid" -) - -type Callback[V any] struct { - callbacks sync.Map -} - -func New[V any]() *Callback[V] { - return &Callback[V]{ - callbacks: sync.Map{}, - } -} - -func (p *Callback[V]) AddMessage(msg V) { - p.callbacks.Range(func(key, value any) bool { - if fn, ok := value.(func(msg V) bool); ok { - go func() { - if !fn(msg) { - p.Unsubscribe(key.(string)) - } - }() - } - - return true - }) -} - -func (p *Callback[V]) Add(fn func(msg V) bool) { - p.callbacks.Store(uuid.NewString(), fn) -} - -func (p *Callback[V]) Subscribe(name string, fn func(msg V) bool) { - p.callbacks.Store(name, fn) -} - -func (p *Callback[V]) Unsubscribe(name string) bool { - _, found := p.callbacks.LoadAndDelete(name) - - return found -} diff --git a/internal/client/enroll.go b/internal/client/enroll.go index edc087fb..dcb4a8a3 100644 --- a/internal/client/enroll.go +++ b/internal/client/enroll.go @@ -20,8 +20,8 @@ import ( "github.com/spf13/viper" "software.sslmate.com/src/go-pkcs12" - "github.com/kdudkov/goatak/pkg/request" "github.com/kdudkov/goatak/pkg/tlsutil" + "github.com/kdudkov/goutils/request" ) const ( diff --git a/pkg/request/request.go b/pkg/request/request.go deleted file mode 100644 index 6fa07906..00000000 --- a/pkg/request/request.go +++ /dev/null @@ -1,158 +0,0 @@ -package request - -import ( - "context" - "encoding/json" - "fmt" - "io" - "log/slog" - "net/http" -) - -type Request struct { - client *http.Client - url string - method string - token string - login string - passw string - body io.Reader - headers map[string]string - args map[string]string - logger *slog.Logger -} - -func New(c *http.Client, logger *slog.Logger) *Request { - return &Request{client: c, method: "GET", logger: logger} -} - -func (r *Request) URL(url string) *Request { - r.url = url - - return r -} - -func (r *Request) Put() *Request { - r.method = "PUT" - - return r -} - -func (r *Request) Post() *Request { - r.method = "POST" - - return r -} - -func (r *Request) Token(token string) *Request { - r.token = token - - return r -} - -func (r *Request) Auth(login, passw string) *Request { - r.login = login - r.passw = passw - - return r -} - -func (r *Request) Headers(headers map[string]string) *Request { - r.headers = headers - - return r -} - -func (r *Request) Args(args map[string]string) *Request { - r.args = args - - return r -} - -func (r *Request) Body(body io.Reader) *Request { - r.body = body - - return r -} - -func (r *Request) DoRes(ctx context.Context) (*http.Response, error) { - req, err := http.NewRequestWithContext(ctx, r.method, r.url, r.body) - if err != nil { - return nil, err - } - - req.Header.Del("User-Agent") - - if len(r.headers) > 0 { - for k, v := range r.headers { - req.Header.Set(k, v) - } - } - - if r.token != "" { - req.Header.Set("Authorization", "Bearer "+r.token) - } else { - if r.login != "" { - req.SetBasicAuth(r.login, r.passw) - } - } - - if len(r.args) > 0 { - q := req.URL.Query() - - for k, v := range r.args { - q.Add(k, v) - } - - req.URL.RawQuery = q.Encode() - } - - res, err := r.client.Do(req) - if err != nil { - if r.logger != nil { - r.logger.Info(fmt.Sprintf("%s %s - error %s", r.method, req.URL, err.Error())) - } - - return res, err - } - - if res.StatusCode < 200 || res.StatusCode > 299 { - if r.logger != nil { - r.logger.Warn(fmt.Sprintf("%s %s - %d", r.method, req.URL, res.StatusCode)) - } - - return res, fmt.Errorf("status is %s", res.Status) - } - - if r.logger != nil { - r.logger.Debug(fmt.Sprintf("%s %s - %d", r.method, req.URL, res.StatusCode)) - } - - return res, nil -} - -func (r *Request) Do(ctx context.Context) (io.ReadCloser, error) { - res, err := r.DoRes(ctx) - - if err != nil { - return nil, err - } - - if res.Body == nil { - return nil, fmt.Errorf("null body") - } - - return res.Body, nil -} - -func (r *Request) GetJSON(ctx context.Context, obj any) error { - b, err := r.Do(ctx) - - if err != nil { - return err - } - - dec := json.NewDecoder(b) - - return dec.Decode(obj) -}