diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 695df67e..50462c74 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -8,6 +8,7 @@ jobs: lint: name: Lint runs-on: ubuntu-24.04 + timeout-minutes: 30 steps: - uses: actions/checkout@v4 with: @@ -22,6 +23,7 @@ jobs: test: name: Unit Tests runs-on: ubuntu-24.04 + timeout-minutes: 30 steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index fe10c79a..9cb940ff 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -6,6 +6,7 @@ jobs: lint: name: Lint runs-on: ubuntu-24.04 + timeout-minutes: 30 steps: - uses: actions/checkout@v4 with: @@ -20,6 +21,7 @@ jobs: test: name: Unit Tests runs-on: ubuntu-24.04 + timeout-minutes: 30 steps: - uses: actions/checkout@v4 with: diff --git a/cli/tests/go.mod b/cli/tests/go.mod index 3a926072..bbbc45eb 100644 --- a/cli/tests/go.mod +++ b/cli/tests/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/cli/tests go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 github.com/stretchr/testify v1.10.0 ) diff --git a/cli/tests/go.sum b/cli/tests/go.sum index 59f4c6a6..c000b6ec 100644 --- a/cli/tests/go.sum +++ b/cli/tests/go.sum @@ -5,8 +5,8 @@ github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2L github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= diff --git a/cli/urfave/go.mod b/cli/urfave/go.mod index b64822fc..01e33fe8 100644 --- a/cli/urfave/go.mod +++ b/cli/urfave/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/cli/urfave go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 github.com/hashicorp/go-multierror v1.1.1 github.com/stretchr/testify v1.10.0 github.com/urfave/cli/v2 v2.27.6 diff --git a/cli/urfave/go.sum b/cli/urfave/go.sum index 147c009f..a64b30ea 100644 --- a/cli/urfave/go.sum +++ b/cli/urfave/go.sum @@ -7,8 +7,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6N github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= diff --git a/client/middleware/log/go.mod b/client/middleware/log/go.mod index eac2939f..efe137a2 100644 --- a/client/middleware/log/go.mod +++ b/client/middleware/log/go.mod @@ -2,7 +2,7 @@ module github.com/go-orb/plugins/client/middleware/log go 1.23.6 -require github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e +require github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 require ( dario.cat/mergo v1.0.1 // indirect diff --git a/client/middleware/log/go.sum b/client/middleware/log/go.sum index fc1a9761..ee496be1 100644 --- a/client/middleware/log/go.sum +++ b/client/middleware/log/go.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/client/middleware/retry/go.mod b/client/middleware/retry/go.mod index 6e5da2cf..418e87c9 100644 --- a/client/middleware/retry/go.mod +++ b/client/middleware/retry/go.mod @@ -2,7 +2,7 @@ module github.com/go-orb/plugins/client/middleware/retry go 1.23.6 -require github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e +require github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 require ( dario.cat/mergo v1.0.1 // indirect diff --git a/client/middleware/retry/go.sum b/client/middleware/retry/go.sum index fc1a9761..ee496be1 100644 --- a/client/middleware/retry/go.sum +++ b/client/middleware/retry/go.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/client/orb/client.go b/client/orb/client.go index d6b99bd9..2d11f130 100644 --- a/client/orb/client.go +++ b/client/orb/client.go @@ -112,54 +112,57 @@ func (c *Client) selectNode(ctx context.Context, service string, opts *client.Ca } // Resolve the service to a list of nodes in a per transport map. - nodes, err := c.resolveService(ctx, service, opts.PreferredTransports...) + nodes, err := c.resolveService(ctx, service, opts) if err != nil { c.Logger().Error("Failed to resolve service", "error", err, "service", service) return "", "", err } // Run the configured Selector to get a node from the resolved nodes. - node, err := opts.Selector(ctx, service, nodes, opts.PreferredTransports, opts.AnyTransport) + node, err := opts.Selector(ctx, service, nodes) if err != nil { c.Logger().Error("Failed to resolve service", "error", err, "service", service) return "", "", err } - return node.Address, node.Transport, nil + return node.Address, node.Scheme, nil } // resolveService resolves a servicename to a Node with the help of the registry. func (c *Client) resolveService( _ context.Context, service string, - preferredTransports ...string, -) (client.NodeMap, error) { + opts *client.CallOptions, +) ([]registry.ServiceNode, error) { if service == "" { return nil, client.ErrServiceArgumentEmpty } // Try to resolve the service with retries var ( - services []*registry.Service + services []registry.ServiceNode err error ) - // Retry up to 3 times with a small delay between attempts - for retries := 0; retries < 1000; retries++ { + // Retry up to 5 times with a small delay between attempts + for retries := 0; retries < 5; retries++ { if _, err := client.ResolveMemoryServer(service); err == nil { - rNodes := make(client.NodeMap) - rNodes["memory"] = []*registry.Node{ - { - ID: "memory", - Address: "", - Transport: "memory", - }, - } + rNodes := make([]registry.ServiceNode, 0) + rNodes = append(rNodes, registry.ServiceNode{ + Name: service, + Scheme: "memory", + Address: "", + }) return rNodes, nil } - services, err = c.registry.GetService(service) + if !opts.AnyTransport { + services, err = c.registry.GetService(context.Background(), opts.Namespace, opts.Region, service, nil) + } else { + services, err = c.registry.GetService(context.Background(), opts.Namespace, opts.Region, service, opts.PreferredTransports) + } + if err == nil && len(services) > 0 { c.logger.Debug("service resolution successful", "service", service) break // Service found, exit retry loop @@ -178,32 +181,12 @@ func (c *Client) resolveService( return nil, fmt.Errorf("no instances found for service: %s", service) } - rNodes := make(client.NodeMap) - - // Find nodes to query - for _, service := range services { - for _, node := range service.Nodes { - tNodes, ok := rNodes[node.Transport] - if !ok { - tNodes = []*registry.Node{} - } - - tNodes = append(tNodes, node) - rNodes[node.Transport] = tNodes - } - } - - // Not one node found. - if len(rNodes) == 0 { - return nil, fmt.Errorf("%w: requested transports was: %s", client.ErrNoNodeFound, preferredTransports) - } - - return rNodes, nil + return services, nil } func (c *Client) makeOptions(opts ...client.CallOption) *client.CallOptions { // Construct CallOptions, use the client's config as base. - co := &client.CallOptions{ + callOpts := &client.CallOptions{ ContentType: c.config.Config.ContentType, PreferredTransports: c.config.Config.PreferredTransports, AnyTransport: c.config.Config.AnyTransport, @@ -222,14 +205,17 @@ func (c *Client) makeOptions(opts ...client.CallOption) *client.CallOptions { Retries: client.DefaultCallOptionsRetries, MaxCallRecvMsgSize: client.DefaultMaxCallRecvMsgSize, MaxCallSendMsgSize: client.DefaultMaxCallSendMsgSize, + + Namespace: c.config.Config.Namespace, + Region: c.config.Config.Region, } // Apply options. for _, o := range opts { - o(co) + o(callOpts) } - return co + return callOpts } func (c *Client) transport(transport string) (Transport, error) { diff --git a/client/orb/go.mod b/client/orb/go.mod index 7ea613b4..c5ffb126 100644 --- a/client/orb/go.mod +++ b/client/orb/go.mod @@ -2,7 +2,7 @@ module github.com/go-orb/plugins/client/orb go 1.23.6 -require github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e +require github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 require ( dario.cat/mergo v1.0.1 // indirect diff --git a/client/orb/go.sum b/client/orb/go.sum index fc1a9761..ee496be1 100644 --- a/client/orb/go.sum +++ b/client/orb/go.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/client/orb_transport/drpc/drpc_test.go b/client/orb_transport/drpc/drpc_test.go index 6dab7d33..e46a5c7f 100644 --- a/client/orb_transport/drpc/drpc_test.go +++ b/client/orb_transport/drpc/drpc_test.go @@ -21,11 +21,11 @@ import ( fileproto "github.com/go-orb/plugins/client/tests/proto/file" // Blank imports here are fine. - _ "github.com/go-orb/plugins-experimental/registry/mdns" _ "github.com/go-orb/plugins/codecs/json" _ "github.com/go-orb/plugins/codecs/proto" _ "github.com/go-orb/plugins/codecs/yaml" _ "github.com/go-orb/plugins/log/slog" + _ "github.com/go-orb/plugins/registry/mdns" ) func setupServer(sn string) (*tests.SetupData, error) { @@ -33,16 +33,14 @@ func setupServer(sn string) (*tests.SetupData, error) { setupData := &tests.SetupData{} - sv := "" - - logger, err := log.New() + logger, err := log.New(log.WithLevel(log.LevelDebug)) if err != nil { cancel() return nil, err } - reg, err := registry.New(sn, sv, nil, &types.Components{}, logger) + reg, err := registry.New(nil, &types.Components{}, logger) if err != nil { cancel() @@ -55,7 +53,11 @@ func setupServer(sn string) (*tests.SetupData, error) { fileHInstance := new(filehandler.Handler) fileHRegister := fileproto.RegisterFileServiceHandler(fileHInstance) - ep, err := drpc.New(drpc.NewConfig(drpc.WithHandlers(echoHRegister, fileHRegister)), logger, reg) + options := []server.Option{ + drpc.WithHandlers(echoHRegister, fileHRegister), + } + + ep, err := drpc.New(sn, "", drpc.NewConfig(options...), logger, reg) if err != nil { cancel() diff --git a/client/orb_transport/drpc/go.mod b/client/orb_transport/drpc/go.mod index f38869de..f8d686bb 100644 --- a/client/orb_transport/drpc/go.mod +++ b/client/orb_transport/drpc/go.mod @@ -3,17 +3,17 @@ module github.com/go-orb/plugins/client/orb_transport/drpc go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3 - github.com/go-orb/plugins/client/orb v0.1.4-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/client/tests v0.2.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/server/drpc v0.1.1-0.20250320235901-3af29c3a3b34 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/client/orb v0.1.4-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/client/tests v0.2.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65 + github.com/go-orb/plugins/server/drpc v0.1.1-0.20250324122813-09813c7b9d65 github.com/stretchr/testify v1.10.0 - google.golang.org/protobuf v1.36.5 + google.golang.org/protobuf v1.36.6 storj.io/drpc v0.0.34 ) @@ -21,19 +21,21 @@ require ( dario.cat/mergo v1.0.1 // indirect github.com/cornelk/hashmap v1.0.8 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/go-orb/plugins/server/http v0.1.1-0.20250320235901-3af29c3a3b34 // indirect - github.com/go-orb/plugins/server/memory v0.0.0-20250320235901-3af29c3a3b34 // indirect + github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 // indirect + github.com/go-orb/plugins/server/http v0.1.1-0.20250324122813-09813c7b9d65 // indirect + github.com/go-orb/plugins/server/memory v0.0.0-20250324122813-09813c7b9d65 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect + github.com/lithammer/shortuuid/v3 v3.0.7 // indirect github.com/miekg/dns v1.1.64 // indirect - github.com/onsi/ginkgo/v2 v2.23.2 // indirect + github.com/onsi/ginkgo/v2 v2.23.3 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/quic-go/qpack v0.5.1 // indirect - github.com/quic-go/quic-go v0.50.0 // indirect + github.com/quic-go/quic-go v0.50.1 // indirect github.com/zeebo/errs v1.4.0 // indirect go.uber.org/mock v0.5.0 // indirect golang.org/x/crypto v0.36.0 // indirect diff --git a/client/orb_transport/drpc/go.sum b/client/orb_transport/drpc/go.sum index c3fd390f..fb366057 100644 --- a/client/orb_transport/drpc/go.sum +++ b/client/orb_transport/drpc/go.sum @@ -8,30 +8,32 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3 h1:aK9T/j8iHppOp8DBUKW32s8/iz4rQm3OKgqM1tT8JVk= -github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3/go.mod h1:A/CzKW0isS1OnxIvMYFJNR+kiEy519aP0o/ptr26HHo= -github.com/go-orb/plugins/client/orb v0.1.4-0.20250320235901-3af29c3a3b34 h1:YIkr44g5X+c8xJHKmXYn27JVNbS6srz6PFMTbSuQNaA= -github.com/go-orb/plugins/client/orb v0.1.4-0.20250320235901-3af29c3a3b34/go.mod h1:cL84wEvOzIPIygJlMq9ce3NSLizT3ezsHTIBZYFQYBY= -github.com/go-orb/plugins/client/tests v0.2.1-0.20250320235901-3af29c3a3b34 h1:aTqdp+CI4we/BV2WRieF7w+g4+6v0IzQ/rZyMySpleA= -github.com/go-orb/plugins/client/tests v0.2.1-0.20250320235901-3af29c3a3b34/go.mod h1:7GClKmT7gQ1PpFBaRw49r/Z/64p3kadMCQJ7o+Aqzx4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= -github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34 h1:VISuyjfVoNEBJmA0amnnnoluqJ+ACGfJQ8Z80NqoVvk= -github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:8DCvAVuNgQtbjfsXp6Wr3GcXw0yhearnn8KJIY6ph9I= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 h1:auojRTYubvH+2JRLgE9I0O8nUrhT2e6sZpKv+IyoQ7U= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:RQ43qp8cY/yyfZ/rukmMVywaEb3IuC50Eq92qekmnUk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 h1:X3NixTLN7+Oqn674kP8t96ztHUspl1CEliCY1bD8Kzk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:w2LKGIQfvocVKtQPmxoGi36ND4cKXicVlfpORu3Irjs= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320212435-efb51edcf7be h1:chFxoVQZSc817Ro4Oh2EQn1gbT8C7fxxBHh3bQW7bqQ= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320212435-efb51edcf7be/go.mod h1:mr+j2640RCvnXxPChwDH4BdvHCFXKuR+ogj2ePtNTWo= -github.com/go-orb/plugins/server/drpc v0.1.1-0.20250320235901-3af29c3a3b34 h1:9ec3ZETU/pKKL3x89+QRdhJc3Twnuq6k20mhIyVGskM= -github.com/go-orb/plugins/server/drpc v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:VOX8mNxDP2RZAv9+0AXjea6MksvDWsDQZkuSxloiP+Q= -github.com/go-orb/plugins/server/http v0.1.1-0.20250320235901-3af29c3a3b34 h1:caNRQ9Imuj/krZKUD7m1XANG/ekhbK4Awqa1ftJI5rA= -github.com/go-orb/plugins/server/http v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:s01/Mif8B7tgVbBo//2sBjXE0JKJP46YMxzFdBuMLy0= -github.com/go-orb/plugins/server/memory v0.0.0-20250320235901-3af29c3a3b34 h1:Lnsdm9PyzpEpr9b4WwYptVAHC/V/phu8WnsguRJxz5M= -github.com/go-orb/plugins/server/memory v0.0.0-20250320235901-3af29c3a3b34/go.mod h1:xyk+XjGuMJwnCkoDG6z3X1AVCUrbhwh89fjMI9dhClQ= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/client/orb v0.1.4-0.20250324122813-09813c7b9d65 h1:PJ8s4U+b/RkjTqSyeMB0OQ/snLEifepmbKN9oWK92F8= +github.com/go-orb/plugins/client/orb v0.1.4-0.20250324122813-09813c7b9d65/go.mod h1:HX/oukRoF9R0NItdG15QkOS2r46C9L3LoH/WyKEV188= +github.com/go-orb/plugins/client/tests v0.2.1-0.20250324122813-09813c7b9d65 h1:kypHHC6OOFPzlJV15IaWALIS1TODmoEOexzjGRgJ8/o= +github.com/go-orb/plugins/client/tests v0.2.1-0.20250324122813-09813c7b9d65/go.mod h1:Z9jNYhxzTh0G/zsjn2D6N5ua4DzJdgS5s+i+SswiFMY= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65 h1:XqBIBUzrQN2XJL7X0LabzFJ26h2Nzf25/owt/2upiW8= +github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:a8/qGJJvPohXYQTnNt1VsQEaQsnOCJIa3sJmoATsTGo= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 h1:2tWSQm0hl6n6cWAaL0MWs7xWYDe7/7/7Gz4ViBiuoQ0= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:18VZ5UrwiOZzMjqNvIHhZLZV640wYCP0X11h2wf8Uq4= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 h1:Fj2tX19g5TxjS9pHyDV4ZMLkZYW4cuNJ6yh149HRJ84= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:U4rbrSlCGhQaiJxl4GRwIQLUv+Cg8og9NEEInd9j8ww= +github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65 h1:KyZnDOqU7JasAljrffIgweV60wJFJsaZi6TZG37H3Ak= +github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65/go.mod h1:cb1WD4avXpSEDYCcdx09hnj62lty2AeO5xe/1IlzuSE= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 h1:6pxnS4Kg1WRSMKU2DFVl40EFlO06YT7gT/d0uK8ZEB4= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:VLPoWEGe+/gcCUZnp3/WJXBP35C22+14CmjrIZegfQY= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122351-5903fde4d556 h1:d/Ma3w7xZE/BeJK7I65vwaA97bi0iy0EoyXNCA3bX/c= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122351-5903fde4d556/go.mod h1:qUq39uHPQ6qZZxNFtH3IPb01vWESqwSJrzUvrzAiBzc= +github.com/go-orb/plugins/server/drpc v0.1.1-0.20250324122813-09813c7b9d65 h1:Kyn3a6lA0gR/TU5LlTuOdJIIJaJc7UWvwHuQYdka4PY= +github.com/go-orb/plugins/server/drpc v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:AExX961zTbbKmxvQh9LNWt+0gtYgKCTE1DH7maR9bNg= +github.com/go-orb/plugins/server/http v0.1.1-0.20250324122813-09813c7b9d65 h1:ryjOOGZMMtlR3eInY5QLpEEwNSqhnRWdghJJMdxBw9I= +github.com/go-orb/plugins/server/http v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:6PZY265CRoAOElxZvyMaQo2W+p1n0dfxO7lw+OTlYJw= +github.com/go-orb/plugins/server/memory v0.0.0-20250324122813-09813c7b9d65 h1:Ks4ETa2dyEpw9FavIVQu+VKyMSolsQTAJ0tmN8fheXU= +github.com/go-orb/plugins/server/memory v0.0.0-20250324122813-09813c7b9d65/go.mod h1:lEHfJvBD8s+9voXJD4aaNqEBRF62a7647iOn+3dCZXU= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -40,6 +42,7 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -53,18 +56,20 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8= +github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts= github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ= github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= -github.com/onsi/ginkgo/v2 v2.23.2 h1:LYLd7Wz401p0N7xR8y7WL6D2QZwKpbirDg0EVIvzvMM= -github.com/onsi/ginkgo/v2 v2.23.2/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= +github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= +github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.50.0 h1:3H/ld1pa3CYhkcc20TPIyG1bNsdhn9qZBGN3b9/UyUo= -github.com/quic-go/quic-go v0.50.0/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= +github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q= +github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -109,8 +114,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/client/orb_transport/grpc/go.mod b/client/orb_transport/grpc/go.mod index 60baffcf..81644711 100644 --- a/client/orb_transport/grpc/go.mod +++ b/client/orb_transport/grpc/go.mod @@ -3,15 +3,15 @@ module github.com/go-orb/plugins/client/orb_transport/grpc go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3 - github.com/go-orb/plugins/client/orb v0.1.4-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/client/tests v0.2.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/server/grpc v0.1.1-0.20250320235901-3af29c3a3b34 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/client/orb v0.1.4-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/client/tests v0.2.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65 + github.com/go-orb/plugins/server/grpc v0.1.1-0.20250324122813-09813c7b9d65 github.com/stretchr/testify v1.10.0 google.golang.org/grpc v1.71.0 ) @@ -20,20 +20,22 @@ require ( dario.cat/mergo v1.0.1 // indirect github.com/cornelk/hashmap v1.0.8 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/go-orb/plugins/server/drpc v0.1.1-0.20250320235901-3af29c3a3b34 // indirect - github.com/go-orb/plugins/server/http v0.1.1-0.20250320235901-3af29c3a3b34 // indirect - github.com/go-orb/plugins/server/memory v0.0.0-20250320235901-3af29c3a3b34 // indirect + github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 // indirect + github.com/go-orb/plugins/server/drpc v0.1.1-0.20250324122813-09813c7b9d65 // indirect + github.com/go-orb/plugins/server/http v0.1.1-0.20250324122813-09813c7b9d65 // indirect + github.com/go-orb/plugins/server/memory v0.0.0-20250324122813-09813c7b9d65 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect + github.com/lithammer/shortuuid/v3 v3.0.7 // indirect github.com/miekg/dns v1.1.64 // indirect - github.com/onsi/ginkgo/v2 v2.23.2 // indirect + github.com/onsi/ginkgo/v2 v2.23.3 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/quic-go/qpack v0.5.1 // indirect - github.com/quic-go/quic-go v0.50.0 // indirect + github.com/quic-go/quic-go v0.50.1 // indirect github.com/zeebo/errs v1.4.0 // indirect go.uber.org/mock v0.5.0 // indirect golang.org/x/crypto v0.36.0 // indirect @@ -45,7 +47,7 @@ require ( golang.org/x/text v0.23.0 // indirect golang.org/x/tools v0.31.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect - google.golang.org/protobuf v1.36.5 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect storj.io/drpc v0.0.34 // indirect ) diff --git a/client/orb_transport/grpc/go.sum b/client/orb_transport/grpc/go.sum index d87ea5ac..28fa782a 100644 --- a/client/orb_transport/grpc/go.sum +++ b/client/orb_transport/grpc/go.sum @@ -8,32 +8,34 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3 h1:aK9T/j8iHppOp8DBUKW32s8/iz4rQm3OKgqM1tT8JVk= -github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3/go.mod h1:A/CzKW0isS1OnxIvMYFJNR+kiEy519aP0o/ptr26HHo= -github.com/go-orb/plugins/client/orb v0.1.4-0.20250320235901-3af29c3a3b34 h1:YIkr44g5X+c8xJHKmXYn27JVNbS6srz6PFMTbSuQNaA= -github.com/go-orb/plugins/client/orb v0.1.4-0.20250320235901-3af29c3a3b34/go.mod h1:cL84wEvOzIPIygJlMq9ce3NSLizT3ezsHTIBZYFQYBY= -github.com/go-orb/plugins/client/tests v0.2.1-0.20250320235901-3af29c3a3b34 h1:aTqdp+CI4we/BV2WRieF7w+g4+6v0IzQ/rZyMySpleA= -github.com/go-orb/plugins/client/tests v0.2.1-0.20250320235901-3af29c3a3b34/go.mod h1:7GClKmT7gQ1PpFBaRw49r/Z/64p3kadMCQJ7o+Aqzx4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= -github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34 h1:VISuyjfVoNEBJmA0amnnnoluqJ+ACGfJQ8Z80NqoVvk= -github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:8DCvAVuNgQtbjfsXp6Wr3GcXw0yhearnn8KJIY6ph9I= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 h1:auojRTYubvH+2JRLgE9I0O8nUrhT2e6sZpKv+IyoQ7U= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:RQ43qp8cY/yyfZ/rukmMVywaEb3IuC50Eq92qekmnUk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 h1:X3NixTLN7+Oqn674kP8t96ztHUspl1CEliCY1bD8Kzk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:w2LKGIQfvocVKtQPmxoGi36ND4cKXicVlfpORu3Irjs= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320212435-efb51edcf7be h1:chFxoVQZSc817Ro4Oh2EQn1gbT8C7fxxBHh3bQW7bqQ= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320212435-efb51edcf7be/go.mod h1:mr+j2640RCvnXxPChwDH4BdvHCFXKuR+ogj2ePtNTWo= -github.com/go-orb/plugins/server/drpc v0.1.1-0.20250320235901-3af29c3a3b34 h1:9ec3ZETU/pKKL3x89+QRdhJc3Twnuq6k20mhIyVGskM= -github.com/go-orb/plugins/server/drpc v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:VOX8mNxDP2RZAv9+0AXjea6MksvDWsDQZkuSxloiP+Q= -github.com/go-orb/plugins/server/grpc v0.1.1-0.20250320235901-3af29c3a3b34 h1:p0boRDb7a/h16JiCRiKjMwg0OCsgLJDuBq9ztL6jQEA= -github.com/go-orb/plugins/server/grpc v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:WkVQEH2+o8IZodEXugQCuo9nd5vvxKXgd0VV503YcFM= -github.com/go-orb/plugins/server/http v0.1.1-0.20250320235901-3af29c3a3b34 h1:caNRQ9Imuj/krZKUD7m1XANG/ekhbK4Awqa1ftJI5rA= -github.com/go-orb/plugins/server/http v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:s01/Mif8B7tgVbBo//2sBjXE0JKJP46YMxzFdBuMLy0= -github.com/go-orb/plugins/server/memory v0.0.0-20250320235901-3af29c3a3b34 h1:Lnsdm9PyzpEpr9b4WwYptVAHC/V/phu8WnsguRJxz5M= -github.com/go-orb/plugins/server/memory v0.0.0-20250320235901-3af29c3a3b34/go.mod h1:xyk+XjGuMJwnCkoDG6z3X1AVCUrbhwh89fjMI9dhClQ= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/client/orb v0.1.4-0.20250324122813-09813c7b9d65 h1:PJ8s4U+b/RkjTqSyeMB0OQ/snLEifepmbKN9oWK92F8= +github.com/go-orb/plugins/client/orb v0.1.4-0.20250324122813-09813c7b9d65/go.mod h1:HX/oukRoF9R0NItdG15QkOS2r46C9L3LoH/WyKEV188= +github.com/go-orb/plugins/client/tests v0.2.1-0.20250324122813-09813c7b9d65 h1:kypHHC6OOFPzlJV15IaWALIS1TODmoEOexzjGRgJ8/o= +github.com/go-orb/plugins/client/tests v0.2.1-0.20250324122813-09813c7b9d65/go.mod h1:Z9jNYhxzTh0G/zsjn2D6N5ua4DzJdgS5s+i+SswiFMY= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65 h1:XqBIBUzrQN2XJL7X0LabzFJ26h2Nzf25/owt/2upiW8= +github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:a8/qGJJvPohXYQTnNt1VsQEaQsnOCJIa3sJmoATsTGo= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 h1:2tWSQm0hl6n6cWAaL0MWs7xWYDe7/7/7Gz4ViBiuoQ0= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:18VZ5UrwiOZzMjqNvIHhZLZV640wYCP0X11h2wf8Uq4= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 h1:Fj2tX19g5TxjS9pHyDV4ZMLkZYW4cuNJ6yh149HRJ84= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:U4rbrSlCGhQaiJxl4GRwIQLUv+Cg8og9NEEInd9j8ww= +github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65 h1:KyZnDOqU7JasAljrffIgweV60wJFJsaZi6TZG37H3Ak= +github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65/go.mod h1:cb1WD4avXpSEDYCcdx09hnj62lty2AeO5xe/1IlzuSE= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 h1:6pxnS4Kg1WRSMKU2DFVl40EFlO06YT7gT/d0uK8ZEB4= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:VLPoWEGe+/gcCUZnp3/WJXBP35C22+14CmjrIZegfQY= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122351-5903fde4d556 h1:d/Ma3w7xZE/BeJK7I65vwaA97bi0iy0EoyXNCA3bX/c= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122351-5903fde4d556/go.mod h1:qUq39uHPQ6qZZxNFtH3IPb01vWESqwSJrzUvrzAiBzc= +github.com/go-orb/plugins/server/drpc v0.1.1-0.20250324122813-09813c7b9d65 h1:Kyn3a6lA0gR/TU5LlTuOdJIIJaJc7UWvwHuQYdka4PY= +github.com/go-orb/plugins/server/drpc v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:AExX961zTbbKmxvQh9LNWt+0gtYgKCTE1DH7maR9bNg= +github.com/go-orb/plugins/server/grpc v0.1.1-0.20250324122813-09813c7b9d65 h1:ulz0E5Gz7CCxvpPIHBrHN7OYea1VmigJguwlz+fZHhY= +github.com/go-orb/plugins/server/grpc v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:2kQ7HKIUG+h6OpK6hMlubQCOd952/3SvRtzjiz5a1dU= +github.com/go-orb/plugins/server/http v0.1.1-0.20250324122813-09813c7b9d65 h1:ryjOOGZMMtlR3eInY5QLpEEwNSqhnRWdghJJMdxBw9I= +github.com/go-orb/plugins/server/http v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:6PZY265CRoAOElxZvyMaQo2W+p1n0dfxO7lw+OTlYJw= +github.com/go-orb/plugins/server/memory v0.0.0-20250324122813-09813c7b9d65 h1:Ks4ETa2dyEpw9FavIVQu+VKyMSolsQTAJ0tmN8fheXU= +github.com/go-orb/plugins/server/memory v0.0.0-20250324122813-09813c7b9d65/go.mod h1:lEHfJvBD8s+9voXJD4aaNqEBRF62a7647iOn+3dCZXU= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -42,6 +44,7 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -55,18 +58,20 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8= +github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts= github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ= github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= -github.com/onsi/ginkgo/v2 v2.23.2 h1:LYLd7Wz401p0N7xR8y7WL6D2QZwKpbirDg0EVIvzvMM= -github.com/onsi/ginkgo/v2 v2.23.2/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= +github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= +github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.50.0 h1:3H/ld1pa3CYhkcc20TPIyG1bNsdhn9qZBGN3b9/UyUo= -github.com/quic-go/quic-go v0.50.0/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= +github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q= +github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -111,8 +116,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/client/orb_transport/grpc/grpc_test.go b/client/orb_transport/grpc/grpc_test.go index 66425bc0..7276d861 100644 --- a/client/orb_transport/grpc/grpc_test.go +++ b/client/orb_transport/grpc/grpc_test.go @@ -21,11 +21,11 @@ import ( fileproto "github.com/go-orb/plugins/client/tests/proto/file" // Blank imports here are fine. - _ "github.com/go-orb/plugins-experimental/registry/mdns" _ "github.com/go-orb/plugins/codecs/json" _ "github.com/go-orb/plugins/codecs/proto" _ "github.com/go-orb/plugins/codecs/yaml" _ "github.com/go-orb/plugins/log/slog" + _ "github.com/go-orb/plugins/registry/mdns" ) func setupServer(sn string) (*tests.SetupData, error) { @@ -33,8 +33,6 @@ func setupServer(sn string) (*tests.SetupData, error) { setupData := &tests.SetupData{} - sv := "" - logger, err := log.New() if err != nil { cancel() @@ -42,7 +40,7 @@ func setupServer(sn string) (*tests.SetupData, error) { return nil, err } - reg, err := registry.New(sn, sv, nil, &types.Components{}, logger) + reg, err := registry.New(nil, &types.Components{}, logger) if err != nil { cancel() @@ -56,6 +54,8 @@ func setupServer(sn string) (*tests.SetupData, error) { fileHRegister := fileproto.RegisterFileServiceHandler(fileHInstance) ep1, err := grpc.New( + sn, + "", grpc.NewConfig(server.WithEntrypointName("grpc"), grpc.WithHandlers(hRegister, fileHRegister), grpc.WithInsecure(), @@ -66,7 +66,12 @@ func setupServer(sn string) (*tests.SetupData, error) { return nil, err } - ep2, err := grpc.New(grpc.NewConfig(server.WithEntrypointName("grpcs"), grpc.WithHandlers(hRegister, fileHRegister)), logger, reg) + ep2, err := grpc.New( + sn, + "", + grpc.NewConfig(server.WithEntrypointName("grpcs"), + grpc.WithHandlers(hRegister, fileHRegister), + ), logger, reg) if err != nil { cancel() diff --git a/client/orb_transport/http/go.mod b/client/orb_transport/http/go.mod index ae7003e1..43c6e20c 100644 --- a/client/orb_transport/http/go.mod +++ b/client/orb_transport/http/go.mod @@ -3,16 +3,16 @@ module github.com/go-orb/plugins/client/orb_transport/http go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3 - github.com/go-orb/plugins/client/orb v0.1.4-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/client/tests v0.2.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/server/http v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/quic-go/quic-go v0.50.0 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/client/orb v0.1.4-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/client/tests v0.2.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65 + github.com/go-orb/plugins/server/http v0.1.1-0.20250324122813-09813c7b9d65 + github.com/quic-go/quic-go v0.50.1 github.com/stretchr/testify v1.10.0 ) @@ -20,16 +20,18 @@ require ( dario.cat/mergo v1.0.1 // indirect github.com/cornelk/hashmap v1.0.8 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/go-orb/plugins/server/drpc v0.1.1-0.20250320235901-3af29c3a3b34 // indirect - github.com/go-orb/plugins/server/memory v0.0.0-20250320235901-3af29c3a3b34 // indirect + github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 // indirect + github.com/go-orb/plugins/server/drpc v0.1.1-0.20250324122813-09813c7b9d65 // indirect + github.com/go-orb/plugins/server/memory v0.0.0-20250324122813-09813c7b9d65 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect + github.com/lithammer/shortuuid/v3 v3.0.7 // indirect github.com/miekg/dns v1.1.64 // indirect - github.com/onsi/ginkgo/v2 v2.23.2 // indirect + github.com/onsi/ginkgo/v2 v2.23.3 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/quic-go/qpack v0.5.1 // indirect github.com/zeebo/errs v1.4.0 // indirect @@ -44,7 +46,7 @@ require ( golang.org/x/tools v0.31.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect google.golang.org/grpc v1.71.0 // indirect - google.golang.org/protobuf v1.36.5 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect storj.io/drpc v0.0.34 // indirect ) diff --git a/client/orb_transport/http/go.sum b/client/orb_transport/http/go.sum index c3fd390f..fb366057 100644 --- a/client/orb_transport/http/go.sum +++ b/client/orb_transport/http/go.sum @@ -8,30 +8,32 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3 h1:aK9T/j8iHppOp8DBUKW32s8/iz4rQm3OKgqM1tT8JVk= -github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3/go.mod h1:A/CzKW0isS1OnxIvMYFJNR+kiEy519aP0o/ptr26HHo= -github.com/go-orb/plugins/client/orb v0.1.4-0.20250320235901-3af29c3a3b34 h1:YIkr44g5X+c8xJHKmXYn27JVNbS6srz6PFMTbSuQNaA= -github.com/go-orb/plugins/client/orb v0.1.4-0.20250320235901-3af29c3a3b34/go.mod h1:cL84wEvOzIPIygJlMq9ce3NSLizT3ezsHTIBZYFQYBY= -github.com/go-orb/plugins/client/tests v0.2.1-0.20250320235901-3af29c3a3b34 h1:aTqdp+CI4we/BV2WRieF7w+g4+6v0IzQ/rZyMySpleA= -github.com/go-orb/plugins/client/tests v0.2.1-0.20250320235901-3af29c3a3b34/go.mod h1:7GClKmT7gQ1PpFBaRw49r/Z/64p3kadMCQJ7o+Aqzx4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= -github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34 h1:VISuyjfVoNEBJmA0amnnnoluqJ+ACGfJQ8Z80NqoVvk= -github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:8DCvAVuNgQtbjfsXp6Wr3GcXw0yhearnn8KJIY6ph9I= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 h1:auojRTYubvH+2JRLgE9I0O8nUrhT2e6sZpKv+IyoQ7U= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:RQ43qp8cY/yyfZ/rukmMVywaEb3IuC50Eq92qekmnUk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 h1:X3NixTLN7+Oqn674kP8t96ztHUspl1CEliCY1bD8Kzk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:w2LKGIQfvocVKtQPmxoGi36ND4cKXicVlfpORu3Irjs= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320212435-efb51edcf7be h1:chFxoVQZSc817Ro4Oh2EQn1gbT8C7fxxBHh3bQW7bqQ= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320212435-efb51edcf7be/go.mod h1:mr+j2640RCvnXxPChwDH4BdvHCFXKuR+ogj2ePtNTWo= -github.com/go-orb/plugins/server/drpc v0.1.1-0.20250320235901-3af29c3a3b34 h1:9ec3ZETU/pKKL3x89+QRdhJc3Twnuq6k20mhIyVGskM= -github.com/go-orb/plugins/server/drpc v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:VOX8mNxDP2RZAv9+0AXjea6MksvDWsDQZkuSxloiP+Q= -github.com/go-orb/plugins/server/http v0.1.1-0.20250320235901-3af29c3a3b34 h1:caNRQ9Imuj/krZKUD7m1XANG/ekhbK4Awqa1ftJI5rA= -github.com/go-orb/plugins/server/http v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:s01/Mif8B7tgVbBo//2sBjXE0JKJP46YMxzFdBuMLy0= -github.com/go-orb/plugins/server/memory v0.0.0-20250320235901-3af29c3a3b34 h1:Lnsdm9PyzpEpr9b4WwYptVAHC/V/phu8WnsguRJxz5M= -github.com/go-orb/plugins/server/memory v0.0.0-20250320235901-3af29c3a3b34/go.mod h1:xyk+XjGuMJwnCkoDG6z3X1AVCUrbhwh89fjMI9dhClQ= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/client/orb v0.1.4-0.20250324122813-09813c7b9d65 h1:PJ8s4U+b/RkjTqSyeMB0OQ/snLEifepmbKN9oWK92F8= +github.com/go-orb/plugins/client/orb v0.1.4-0.20250324122813-09813c7b9d65/go.mod h1:HX/oukRoF9R0NItdG15QkOS2r46C9L3LoH/WyKEV188= +github.com/go-orb/plugins/client/tests v0.2.1-0.20250324122813-09813c7b9d65 h1:kypHHC6OOFPzlJV15IaWALIS1TODmoEOexzjGRgJ8/o= +github.com/go-orb/plugins/client/tests v0.2.1-0.20250324122813-09813c7b9d65/go.mod h1:Z9jNYhxzTh0G/zsjn2D6N5ua4DzJdgS5s+i+SswiFMY= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65 h1:XqBIBUzrQN2XJL7X0LabzFJ26h2Nzf25/owt/2upiW8= +github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:a8/qGJJvPohXYQTnNt1VsQEaQsnOCJIa3sJmoATsTGo= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 h1:2tWSQm0hl6n6cWAaL0MWs7xWYDe7/7/7Gz4ViBiuoQ0= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:18VZ5UrwiOZzMjqNvIHhZLZV640wYCP0X11h2wf8Uq4= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 h1:Fj2tX19g5TxjS9pHyDV4ZMLkZYW4cuNJ6yh149HRJ84= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:U4rbrSlCGhQaiJxl4GRwIQLUv+Cg8og9NEEInd9j8ww= +github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65 h1:KyZnDOqU7JasAljrffIgweV60wJFJsaZi6TZG37H3Ak= +github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65/go.mod h1:cb1WD4avXpSEDYCcdx09hnj62lty2AeO5xe/1IlzuSE= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 h1:6pxnS4Kg1WRSMKU2DFVl40EFlO06YT7gT/d0uK8ZEB4= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:VLPoWEGe+/gcCUZnp3/WJXBP35C22+14CmjrIZegfQY= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122351-5903fde4d556 h1:d/Ma3w7xZE/BeJK7I65vwaA97bi0iy0EoyXNCA3bX/c= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122351-5903fde4d556/go.mod h1:qUq39uHPQ6qZZxNFtH3IPb01vWESqwSJrzUvrzAiBzc= +github.com/go-orb/plugins/server/drpc v0.1.1-0.20250324122813-09813c7b9d65 h1:Kyn3a6lA0gR/TU5LlTuOdJIIJaJc7UWvwHuQYdka4PY= +github.com/go-orb/plugins/server/drpc v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:AExX961zTbbKmxvQh9LNWt+0gtYgKCTE1DH7maR9bNg= +github.com/go-orb/plugins/server/http v0.1.1-0.20250324122813-09813c7b9d65 h1:ryjOOGZMMtlR3eInY5QLpEEwNSqhnRWdghJJMdxBw9I= +github.com/go-orb/plugins/server/http v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:6PZY265CRoAOElxZvyMaQo2W+p1n0dfxO7lw+OTlYJw= +github.com/go-orb/plugins/server/memory v0.0.0-20250324122813-09813c7b9d65 h1:Ks4ETa2dyEpw9FavIVQu+VKyMSolsQTAJ0tmN8fheXU= +github.com/go-orb/plugins/server/memory v0.0.0-20250324122813-09813c7b9d65/go.mod h1:lEHfJvBD8s+9voXJD4aaNqEBRF62a7647iOn+3dCZXU= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -40,6 +42,7 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -53,18 +56,20 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8= +github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts= github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ= github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= -github.com/onsi/ginkgo/v2 v2.23.2 h1:LYLd7Wz401p0N7xR8y7WL6D2QZwKpbirDg0EVIvzvMM= -github.com/onsi/ginkgo/v2 v2.23.2/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= +github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= +github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.50.0 h1:3H/ld1pa3CYhkcc20TPIyG1bNsdhn9qZBGN3b9/UyUo= -github.com/quic-go/quic-go v0.50.0/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= +github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q= +github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -109,8 +114,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/client/orb_transport/http/http_test.go b/client/orb_transport/http/http_test.go index 8a11c388..7f65f609 100644 --- a/client/orb_transport/http/http_test.go +++ b/client/orb_transport/http/http_test.go @@ -18,11 +18,11 @@ import ( echoproto "github.com/go-orb/plugins/client/tests/proto/echo" // Blank imports here are fine. - _ "github.com/go-orb/plugins-experimental/registry/mdns" _ "github.com/go-orb/plugins/codecs/json" _ "github.com/go-orb/plugins/codecs/proto" _ "github.com/go-orb/plugins/codecs/yaml" _ "github.com/go-orb/plugins/log/slog" + _ "github.com/go-orb/plugins/registry/mdns" ) func setupServer(sn string) (*tests.SetupData, error) { @@ -30,8 +30,6 @@ func setupServer(sn string) (*tests.SetupData, error) { setupData := &tests.SetupData{} - sv := "" - logger, err := log.New() if err != nil { cancel() @@ -39,7 +37,7 @@ func setupServer(sn string) (*tests.SetupData, error) { return nil, err } - reg, err := registry.New(sn, sv, nil, &types.Components{}, logger) + reg, err := registry.New(nil, &types.Components{}, logger) if err != nil { cancel() @@ -50,6 +48,8 @@ func setupServer(sn string) (*tests.SetupData, error) { hRegister := echoproto.RegisterStreamsHandler(hInstance) ep1, err := http.New( + sn, + "", http.NewConfig( server.WithEntrypointName("http"), http.WithHandlers(hRegister), @@ -65,6 +65,8 @@ func setupServer(sn string) (*tests.SetupData, error) { } ep2, err := http.New( + sn, + "", http.NewConfig( server.WithEntrypointName("h2c"), http.WithHandlers(hRegister), @@ -80,6 +82,8 @@ func setupServer(sn string) (*tests.SetupData, error) { return nil, err } ep3, err := http.New( + sn, + "", http.NewConfig( server.WithEntrypointName("https"), http.WithHandlers(hRegister), @@ -93,6 +97,8 @@ func setupServer(sn string) (*tests.SetupData, error) { return nil, err } ep4, err := http.New( + sn, + "", http.NewConfig( server.WithEntrypointName("http3"), http.WithHandlers(hRegister), diff --git a/client/tests/go.mod b/client/tests/go.mod index 4c47fdc0..a424f599 100644 --- a/client/tests/go.mod +++ b/client/tests/go.mod @@ -3,14 +3,14 @@ module github.com/go-orb/plugins/client/tests go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins/server/drpc v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/server/http v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/server/memory v0.0.0-20250320235901-3af29c3a3b34 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/server/drpc v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/server/http v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/server/memory v0.0.0-20250324122813-09813c7b9d65 github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.10.0 google.golang.org/grpc v1.71.0 - google.golang.org/protobuf v1.36.5 + google.golang.org/protobuf v1.36.6 storj.io/drpc v0.0.34 ) @@ -24,10 +24,10 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/kr/pretty v0.3.1 // indirect - github.com/onsi/ginkgo/v2 v2.23.2 // indirect + github.com/onsi/ginkgo/v2 v2.23.3 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/quic-go/qpack v0.5.1 // indirect - github.com/quic-go/quic-go v0.50.0 // indirect + github.com/quic-go/quic-go v0.50.1 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/zeebo/errs v1.4.0 // indirect go.uber.org/mock v0.5.0 // indirect diff --git a/client/tests/go.sum b/client/tests/go.sum index 0d9bcc3d..2cc273e9 100644 --- a/client/tests/go.sum +++ b/client/tests/go.sum @@ -9,14 +9,14 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins/server/drpc v0.1.1-0.20250320235901-3af29c3a3b34 h1:9ec3ZETU/pKKL3x89+QRdhJc3Twnuq6k20mhIyVGskM= -github.com/go-orb/plugins/server/drpc v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:VOX8mNxDP2RZAv9+0AXjea6MksvDWsDQZkuSxloiP+Q= -github.com/go-orb/plugins/server/http v0.1.1-0.20250320235901-3af29c3a3b34 h1:caNRQ9Imuj/krZKUD7m1XANG/ekhbK4Awqa1ftJI5rA= -github.com/go-orb/plugins/server/http v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:s01/Mif8B7tgVbBo//2sBjXE0JKJP46YMxzFdBuMLy0= -github.com/go-orb/plugins/server/memory v0.0.0-20250320235901-3af29c3a3b34 h1:Lnsdm9PyzpEpr9b4WwYptVAHC/V/phu8WnsguRJxz5M= -github.com/go-orb/plugins/server/memory v0.0.0-20250320235901-3af29c3a3b34/go.mod h1:xyk+XjGuMJwnCkoDG6z3X1AVCUrbhwh89fjMI9dhClQ= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/server/drpc v0.1.1-0.20250324122813-09813c7b9d65 h1:Kyn3a6lA0gR/TU5LlTuOdJIIJaJc7UWvwHuQYdka4PY= +github.com/go-orb/plugins/server/drpc v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:AExX961zTbbKmxvQh9LNWt+0gtYgKCTE1DH7maR9bNg= +github.com/go-orb/plugins/server/http v0.1.1-0.20250324122813-09813c7b9d65 h1:ryjOOGZMMtlR3eInY5QLpEEwNSqhnRWdghJJMdxBw9I= +github.com/go-orb/plugins/server/http v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:6PZY265CRoAOElxZvyMaQo2W+p1n0dfxO7lw+OTlYJw= +github.com/go-orb/plugins/server/memory v0.0.0-20250324122813-09813c7b9d65 h1:Ks4ETa2dyEpw9FavIVQu+VKyMSolsQTAJ0tmN8fheXU= +github.com/go-orb/plugins/server/memory v0.0.0-20250324122813-09813c7b9d65/go.mod h1:lEHfJvBD8s+9voXJD4aaNqEBRF62a7647iOn+3dCZXU= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -41,8 +41,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/onsi/ginkgo/v2 v2.23.2 h1:LYLd7Wz401p0N7xR8y7WL6D2QZwKpbirDg0EVIvzvMM= -github.com/onsi/ginkgo/v2 v2.23.2/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= +github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= +github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -50,8 +50,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.50.0 h1:3H/ld1pa3CYhkcc20TPIyG1bNsdhn9qZBGN3b9/UyUo= -github.com/quic-go/quic-go v0.50.0/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= +github.com/quic-go/quic-go v0.50.1 h1:unsgjFIUqW8a2oopkY7YNONpV1gYND6Nt9hnt1PN94Q= +github.com/quic-go/quic-go v0.50.1/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= @@ -97,8 +97,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/client/tests/tests.go b/client/tests/tests.go index 9bc1046d..6a2feb17 100644 --- a/client/tests/tests.go +++ b/client/tests/tests.go @@ -141,7 +141,8 @@ type TestSuite struct { } // NewSuite creates a new test suite. -func NewSuite(setupServer func(service string) (*SetupData, error), transports []string, requests ...TestRequest) *TestSuite { +func NewSuite(setupServer func(service string) (*SetupData, error), + transports []string, requests ...TestRequest) *TestSuite { s := new(TestSuite) s.Transports = transports diff --git a/codecs/form/go.mod b/codecs/form/go.mod index 2f9a56a1..c8708faa 100644 --- a/codecs/form/go.mod +++ b/codecs/form/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/codecs/form go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 github.com/go-playground/form/v4 v4.2.1 github.com/stretchr/testify v1.10.0 google.golang.org/protobuf v1.36.5 diff --git a/codecs/form/go.sum b/codecs/form/go.sum index 60edf76f..e5077861 100644 --- a/codecs/form/go.sum +++ b/codecs/form/go.sum @@ -3,8 +3,8 @@ github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2L github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= diff --git a/codecs/goccyjson/go.mod b/codecs/goccyjson/go.mod index e56ba093..1138735f 100644 --- a/codecs/goccyjson/go.mod +++ b/codecs/goccyjson/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/codecs/goccyjson go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 github.com/goccy/go-json v0.10.5 ) diff --git a/codecs/goccyjson/go.sum b/codecs/goccyjson/go.sum index 4cda5b38..e59dac50 100644 --- a/codecs/goccyjson/go.sum +++ b/codecs/goccyjson/go.sum @@ -1,6 +1,6 @@ github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= diff --git a/codecs/json/go.mod b/codecs/json/go.mod index a6623437..28d2c4f3 100644 --- a/codecs/json/go.mod +++ b/codecs/json/go.mod @@ -2,6 +2,6 @@ module github.com/go-orb/plugins/codecs/json go 1.23.6 -require github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e +require github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 require github.com/cornelk/hashmap v1.0.8 // indirect diff --git a/codecs/json/go.sum b/codecs/json/go.sum index bad0a2b4..b98f76b8 100644 --- a/codecs/json/go.sum +++ b/codecs/json/go.sum @@ -1,4 +1,4 @@ github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= diff --git a/codecs/jsonpb/go.mod b/codecs/jsonpb/go.mod index 77df4686..c634eba1 100644 --- a/codecs/jsonpb/go.mod +++ b/codecs/jsonpb/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/codecs/jsonpb go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 google.golang.org/protobuf v1.36.5 ) diff --git a/codecs/jsonpb/go.sum b/codecs/jsonpb/go.sum index 39a4499d..1e06e0c1 100644 --- a/codecs/jsonpb/go.sum +++ b/codecs/jsonpb/go.sum @@ -1,7 +1,7 @@ github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= diff --git a/codecs/proto/go.mod b/codecs/proto/go.mod index 8652ca57..ebf42c2c 100644 --- a/codecs/proto/go.mod +++ b/codecs/proto/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/codecs/proto go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 google.golang.org/protobuf v1.36.5 ) diff --git a/codecs/proto/go.sum b/codecs/proto/go.sum index 39a4499d..1e06e0c1 100644 --- a/codecs/proto/go.sum +++ b/codecs/proto/go.sum @@ -1,7 +1,7 @@ github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= diff --git a/codecs/toml/go.mod b/codecs/toml/go.mod index f052263e..e6145dd2 100644 --- a/codecs/toml/go.mod +++ b/codecs/toml/go.mod @@ -4,7 +4,7 @@ go 1.23.6 require ( github.com/BurntSushi/toml v1.5.0 - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 ) require github.com/cornelk/hashmap v1.0.8 // indirect diff --git a/codecs/toml/go.sum b/codecs/toml/go.sum index 42a859e5..28326768 100644 --- a/codecs/toml/go.sum +++ b/codecs/toml/go.sum @@ -2,5 +2,5 @@ github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= diff --git a/codecs/yaml/go.mod b/codecs/yaml/go.mod index a6c67c12..ba4aba9b 100644 --- a/codecs/yaml/go.mod +++ b/codecs/yaml/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/codecs/yaml go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/codecs/yaml/go.sum b/codecs/yaml/go.sum index 65c3601c..b9985847 100644 --- a/codecs/yaml/go.sum +++ b/codecs/yaml/go.sum @@ -1,8 +1,8 @@ github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= diff --git a/config/source/file/go.mod b/config/source/file/go.mod index 7a4b3232..87c6d54e 100644 --- a/config/source/file/go.mod +++ b/config/source/file/go.mod @@ -3,16 +3,16 @@ module github.com/go-orb/plugins/config/source/file go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 github.com/stretchr/testify v1.10.0 ) require ( dario.cat/mergo v1.0.1 // indirect github.com/cornelk/hashmap v1.0.8 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/config/source/file/go.sum b/config/source/file/go.sum index ce6796da..a0e18f19 100644 --- a/config/source/file/go.sum +++ b/config/source/file/go.sum @@ -3,14 +3,14 @@ dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 h1:auojRTYubvH+2JRLgE9I0O8nUrhT2e6sZpKv+IyoQ7U= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:RQ43qp8cY/yyfZ/rukmMVywaEb3IuC50Eq92qekmnUk= +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/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 h1:2tWSQm0hl6n6cWAaL0MWs7xWYDe7/7/7Gz4ViBiuoQ0= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:18VZ5UrwiOZzMjqNvIHhZLZV640wYCP0X11h2wf8Uq4= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= diff --git a/config/source/http/go.mod b/config/source/http/go.mod index 971ddc34..99819bf4 100644 --- a/config/source/http/go.mod +++ b/config/source/http/go.mod @@ -2,7 +2,7 @@ module github.com/go-orb/plugins/config/source/http go 1.23.6 -require github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e +require github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 require ( dario.cat/mergo v1.0.1 // indirect diff --git a/config/source/http/go.sum b/config/source/http/go.sum index fc1a9761..ee496be1 100644 --- a/config/source/http/go.sum +++ b/config/source/http/go.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/config/tests/go.mod b/config/tests/go.mod index 0b493ee1..f00802ed 100644 --- a/config/tests/go.mod +++ b/config/tests/go.mod @@ -3,11 +3,11 @@ module github.com/go-orb/plugins/config/tests go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/config/source/file v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/config/source/http v0.1.1-0.20250320235901-3af29c3a3b34 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/config/source/file v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/config/source/http v0.1.1-0.20250324122813-09813c7b9d65 github.com/stretchr/testify v1.10.0 ) diff --git a/config/tests/go.sum b/config/tests/go.sum index d6a9d01c..8189521d 100644 --- a/config/tests/go.sum +++ b/config/tests/go.sum @@ -4,16 +4,16 @@ github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= 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/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 h1:auojRTYubvH+2JRLgE9I0O8nUrhT2e6sZpKv+IyoQ7U= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:RQ43qp8cY/yyfZ/rukmMVywaEb3IuC50Eq92qekmnUk= -github.com/go-orb/plugins/config/source/file v0.1.1-0.20250320235901-3af29c3a3b34 h1:KuPHiH1lkxdy4pzbXRjtBgf9X8S0l8eSaCPO5WMj/VE= -github.com/go-orb/plugins/config/source/file v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:4P+GclfUx1+m1Zur9EXKMXT5F84EMhD6yzJmUYQV5Is= -github.com/go-orb/plugins/config/source/http v0.1.1-0.20250320235901-3af29c3a3b34 h1:rYj01wI9524gMc/KRgBefNEeuoq2acRhCKfUGbzUMrg= -github.com/go-orb/plugins/config/source/http v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:E8iIbpi6RHQlVTqqqyEpcubqxgzJDv0/N/JCN0KpF9c= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 h1:2tWSQm0hl6n6cWAaL0MWs7xWYDe7/7/7Gz4ViBiuoQ0= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:18VZ5UrwiOZzMjqNvIHhZLZV640wYCP0X11h2wf8Uq4= +github.com/go-orb/plugins/config/source/file v0.1.1-0.20250324122813-09813c7b9d65 h1:0hJ6LxqnafPrJE/2rd9Fk2wKACRpqwd+Y4eBc3hYTK0= +github.com/go-orb/plugins/config/source/file v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:WL/+LubUXw4blqd/az/8/4X4m1QQgB4wOEPy2MObJsY= +github.com/go-orb/plugins/config/source/http v0.1.1-0.20250324122813-09813c7b9d65 h1:0fIo0lhS1/cMxTUamhE+E40Pq2Z3msLug/81Lebg/js= +github.com/go-orb/plugins/config/source/http v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:fZ6yU2TdO8gVJziKjYuj8CA9RkSdXaES11albjJCKnc= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= diff --git a/event/natsjs/go.mod b/event/natsjs/go.mod index 321db79a..d2e34851 100644 --- a/event/natsjs/go.mod +++ b/event/natsjs/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/event/natsjs go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 github.com/google/uuid v1.6.0 github.com/nats-io/nats.go v1.39.1 google.golang.org/protobuf v1.36.5 diff --git a/event/natsjs/go.sum b/event/natsjs/go.sum index fd47b41f..d65d4b2c 100644 --- a/event/natsjs/go.sum +++ b/event/natsjs/go.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/event/tests/go.mod b/event/tests/go.mod index 3c9e9165..8038adc1 100644 --- a/event/tests/go.mod +++ b/event/tests/go.mod @@ -3,13 +3,13 @@ module github.com/go-orb/plugins/event/tests go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/event/natsjs v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/event/natsjs v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 github.com/stretchr/testify v1.10.0 - google.golang.org/protobuf v1.36.5 + google.golang.org/protobuf v1.36.6 ) require ( diff --git a/event/tests/go.sum b/event/tests/go.sum index 8ba3c266..88102cbf 100644 --- a/event/tests/go.sum +++ b/event/tests/go.sum @@ -5,16 +5,16 @@ github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2L github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= -github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34 h1:VISuyjfVoNEBJmA0amnnnoluqJ+ACGfJQ8Z80NqoVvk= -github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:8DCvAVuNgQtbjfsXp6Wr3GcXw0yhearnn8KJIY6ph9I= -github.com/go-orb/plugins/event/natsjs v0.1.1-0.20250320235901-3af29c3a3b34 h1:7BGVnIGrXd/VDOtveQNY+OHBquWxD+mRrpN97BVdpSU= -github.com/go-orb/plugins/event/natsjs v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:s77eluMhK8yWEX9Eyn4wK8NoJ57pTJf6zDiGqb0zYJo= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 h1:X3NixTLN7+Oqn674kP8t96ztHUspl1CEliCY1bD8Kzk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:w2LKGIQfvocVKtQPmxoGi36ND4cKXicVlfpORu3Irjs= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65 h1:XqBIBUzrQN2XJL7X0LabzFJ26h2Nzf25/owt/2upiW8= +github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:a8/qGJJvPohXYQTnNt1VsQEaQsnOCJIa3sJmoATsTGo= +github.com/go-orb/plugins/event/natsjs v0.1.1-0.20250324122813-09813c7b9d65 h1:XcvBSJNTPf3+eZ7cVARk/XvphrK3yJJGSXnyzxN8aNw= +github.com/go-orb/plugins/event/natsjs v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:UMmFUCYoNMgUgQdP8X3PylYICaIn1q9qXYRUOBNWHkw= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 h1:Fj2tX19g5TxjS9pHyDV4ZMLkZYW4cuNJ6yh149HRJ84= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:U4rbrSlCGhQaiJxl4GRwIQLUv+Cg8og9NEEInd9j8ww= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -46,8 +46,8 @@ golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/kvstore/natsjs/go.mod b/kvstore/natsjs/go.mod index 353438e0..626f30eb 100644 --- a/kvstore/natsjs/go.mod +++ b/kvstore/natsjs/go.mod @@ -4,8 +4,8 @@ go 1.23.6 require ( github.com/cornelk/hashmap v1.0.8 - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 github.com/nats-io/nats-server/v2 v2.10.26 github.com/nats-io/nats.go v1.39.1 github.com/stretchr/testify v1.10.0 diff --git a/kvstore/natsjs/go.sum b/kvstore/natsjs/go.sum index 4a7885e1..22bdf38a 100644 --- a/kvstore/natsjs/go.sum +++ b/kvstore/natsjs/go.sum @@ -5,10 +5,10 @@ github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2L github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= diff --git a/kvstore/natsjs_micro_tests/go.mod b/kvstore/natsjs_micro_tests/go.mod index 815240fc..fc64dd80 100644 --- a/kvstore/natsjs_micro_tests/go.mod +++ b/kvstore/natsjs_micro_tests/go.mod @@ -6,10 +6,10 @@ toolchain go1.24.0 require ( github.com/go-micro/plugins/v4/store/nats-js-kv v0.0.0-20240726082623-6831adfdcdc4 - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/kvstore/natsjs v0.0.0-20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/kvstore/natsjs v0.0.0-20250324122813-09813c7b9d65 + github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 github.com/nats-io/nats-server/v2 v2.10.26 github.com/nats-io/nats.go v1.39.1 github.com/stretchr/testify v1.10.0 @@ -38,7 +38,7 @@ require ( github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/compress v1.18.0 // indirect - github.com/miekg/dns v1.1.63 // indirect + github.com/miekg/dns v1.1.64 // indirect github.com/minio/highwayhash v1.0.3 // indirect github.com/nats-io/jwt/v2 v2.7.3 // indirect github.com/nats-io/nkeys v0.4.10 // indirect diff --git a/kvstore/natsjs_micro_tests/go.sum b/kvstore/natsjs_micro_tests/go.sum index 11328d85..3a2da685 100644 --- a/kvstore/natsjs_micro_tests/go.sum +++ b/kvstore/natsjs_micro_tests/go.sum @@ -42,14 +42,14 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60= github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= -github.com/go-orb/plugins/kvstore/natsjs v0.0.0-20250320235901-3af29c3a3b34 h1:UITXn5ryhxgtHGcVJ222RrvWsIRyOdhp6xyeNusoG9s= -github.com/go-orb/plugins/kvstore/natsjs v0.0.0-20250320235901-3af29c3a3b34/go.mod h1:MLRHZy7j8WaYIbZurf1A/GQwndaOs4h9y6yVA5xnrck= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 h1:X3NixTLN7+Oqn674kP8t96ztHUspl1CEliCY1bD8Kzk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:w2LKGIQfvocVKtQPmxoGi36ND4cKXicVlfpORu3Irjs= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/kvstore/natsjs v0.0.0-20250324122813-09813c7b9d65 h1:xII5JMxM+uEgRIvw6M+FEvxaYiHEOjF9632/bfd+AGM= +github.com/go-orb/plugins/kvstore/natsjs v0.0.0-20250324122813-09813c7b9d65/go.mod h1:Uoc9J4khEzaKxLiftCsIYEtxdn8+EX3+e/HBPUgMWxc= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 h1:Fj2tX19g5TxjS9pHyDV4ZMLkZYW4cuNJ6yh149HRJ84= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:U4rbrSlCGhQaiJxl4GRwIQLUv+Cg8og9NEEInd9j8ww= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -75,8 +75,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= -github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= +github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ= +github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= github.com/nats-io/jwt/v2 v2.7.3 h1:6bNPK+FXgBeAqdj4cYQ0F8ViHRbi7woQLq4W29nUAzE= diff --git a/log/lumberjack/go.mod b/log/lumberjack/go.mod index 88960b3e..078d6bb6 100644 --- a/log/lumberjack/go.mod +++ b/log/lumberjack/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/log/lumberjack go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) diff --git a/log/lumberjack/go.sum b/log/lumberjack/go.sum index 4aaefb17..c6a46ace 100644 --- a/log/lumberjack/go.sum +++ b/log/lumberjack/go.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= diff --git a/log/slog/go.mod b/log/slog/go.mod index ce374e64..a31bbc85 100644 --- a/log/slog/go.mod +++ b/log/slog/go.mod @@ -3,8 +3,8 @@ module github.com/go-orb/plugins/log/slog go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 github.com/stretchr/testify v1.10.0 ) diff --git a/log/slog/go.sum b/log/slog/go.sum index 28de35b4..6f710137 100644 --- a/log/slog/go.sum +++ b/log/slog/go.sum @@ -5,10 +5,10 @@ github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2L github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= diff --git a/registry/consul/config.go b/registry/consul/config.go index 112c53b1..ae0f50d1 100644 --- a/registry/consul/config.go +++ b/registry/consul/config.go @@ -9,9 +9,7 @@ import ( "github.com/go-orb/go-orb/registry" ) -// metaTransportKey is the key to use to store the scheme in metadata. -const metaTransportKey = "__consul__transport" -const metaNodeIDKey = "__consul__node-id" +const metaPrefix = "orb_app_" // Name provides the name of this registry. const Name = "consul" diff --git a/registry/consul/consul.go b/registry/consul/consul.go index 2f154a18..cc4f43eb 100644 --- a/registry/consul/consul.go +++ b/registry/consul/consul.go @@ -6,7 +6,6 @@ import ( "crypto/tls" "errors" "fmt" - "maps" "net" "net/http" "runtime" @@ -15,31 +14,66 @@ import ( "strings" "time" + consul "github.com/hashicorp/consul/api" + "github.com/go-orb/go-orb/config" "github.com/go-orb/go-orb/log" "github.com/go-orb/go-orb/registry" "github.com/go-orb/go-orb/types" - maddr "github.com/go-orb/go-orb/util/addr" + "github.com/go-orb/plugins/registry/regutil/cache" - "github.com/google/uuid" - consul "github.com/hashicorp/consul/api" - "github.com/hashicorp/go-multierror" ) +const nodeIDDelimiter = "@" + +func nodeID(s registry.ServiceNode) string { + return strings.Join([]string{ + s.Namespace, + s.Region, + s.Name, + s.Version, + s.Scheme, + s.Address, + }, nodeIDDelimiter) +} + +func idToNode(id string) (registry.ServiceNode, error) { + parts := strings.Split(id, nodeIDDelimiter) + if len(parts) != 6 { + return registry.ServiceNode{}, errors.New("invalid id format") + } + + return registry.ServiceNode{ + Namespace: parts[0], + Region: parts[1], + Name: parts[2], + Version: parts[3], + Scheme: parts[4], + Address: parts[5], + Metadata: make(map[string]string), + }, nil +} + +func splitID(id string) (string, string, string) { + splits := strings.Split(id, nodeIDDelimiter) + + return splits[0], splits[1], splits[2] +} + +func idToPrefix(id string) string { + return strings.Join(strings.Split(id, nodeIDDelimiter)[:3], nodeIDDelimiter) + nodeIDDelimiter +} + // This is here to make sure RegistryConsul implements registry.Registry. var _ registry.Registry = (*RegistryConsul)(nil) // RegistryConsul is the consul registry for go-orb. type RegistryConsul struct { - Address []string - serviceName string - serviceVersion string + Address []string config Config logger log.Logger - id string - client *consul.Client consulConfig *consul.Config @@ -85,161 +119,92 @@ func newTransport(config *tls.Config) *http.Transport { return t } -// ServiceName returns the configured name of this service. -func (c *RegistryConsul) ServiceName() string { - return c.serviceName -} - -// ServiceVersion returns the configured version of this service. -func (c *RegistryConsul) ServiceVersion() string { - return c.serviceVersion -} - -// NodeID returns the ID of this service node in the registry. -func (c *RegistryConsul) NodeID() string { - if c.id != "" { - return c.id - } - - c.id = uuid.New().String() - - return c.id -} - // Deregister deregisters a service within the registry. -func (c *RegistryConsul) Deregister(s *registry.Service, _ ...registry.DeregisterOption) error { - if len(s.Nodes) == 0 { - return errors.New("require at least one node") - } - - var mErr *multierror.Error - for _, node := range s.Nodes { - mErr = multierror.Append( - mErr, - c.Client().Agent().ServiceDeregister(s.Name+"-"+node.ID+"-"+node.Transport), - ) - } - - return mErr.ErrorOrNil() +func (c *RegistryConsul) Deregister(_ context.Context, serviceNode registry.ServiceNode) error { + return c.Client().Agent().ServiceDeregister(nodeID(serviceNode)) } // Register registers a service within the registry. -// -//nolint:funlen,gocyclo -func (c *RegistryConsul) Register(service *registry.Service, opts ...registry.RegisterOption) error { - if len(service.Nodes) == 0 { - return errors.New("require at least one node") - } - +func (c *RegistryConsul) Register(_ context.Context, serviceNode registry.ServiceNode) error { var ( regTCPCheck bool regInterval time.Duration - options registry.RegisterOptions ) - for _, o := range opts { - o(&options) - } - if c.config.TCPCheck > 0 { regTCPCheck = true regInterval = c.config.TCPCheck } - // use all nodes - for _, node := range service.Nodes { - // encode the tags - tags := encodeEndpoints(service.Endpoints) - tags = append(tags, encodeVersion(service.Version)...) - - var check *consul.AgentServiceCheck + var check *consul.AgentServiceCheck - if regTCPCheck { - deregTTL := getDeregisterTTL(regInterval) + if regTCPCheck { + deregTTL := getDeregisterTTL(regInterval) - check = &consul.AgentServiceCheck{ - TCP: node.Address, - Interval: fmt.Sprintf("%v", regInterval), - DeregisterCriticalServiceAfter: fmt.Sprintf("%v", deregTTL), - } - } else if options.TTL > time.Duration(0) { - // if the TTL is greater than 0 create an associated check - deregTTL := getDeregisterTTL(options.TTL) - - check = &consul.AgentServiceCheck{ - TTL: fmt.Sprintf("%v", options.TTL), - DeregisterCriticalServiceAfter: fmt.Sprintf("%v", deregTTL), - } + check = &consul.AgentServiceCheck{ + TCP: serviceNode.Address, + Interval: fmt.Sprintf("%v", regInterval), + DeregisterCriticalServiceAfter: fmt.Sprintf("%v", deregTTL), } + } else if serviceNode.TTL > time.Duration(0) { + // if the TTL is greater than 0 create an associated check + deregTTL := getDeregisterTTL(serviceNode.TTL) - host, pt, err := net.SplitHostPort(node.Address) - if err != nil { - return err - } - - if host == "" { - host = node.Address - } - - port, err := strconv.Atoi(pt) - if err != nil { - return err - } - - metadata := map[string]string{} - // Add service metadata to the service - for k, v := range service.Metadata { - metadata["orb_service_"+k] = v + check = &consul.AgentServiceCheck{ + TTL: fmt.Sprintf("%v", serviceNode.TTL), + DeregisterCriticalServiceAfter: fmt.Sprintf("%v", deregTTL), } + } - metadata["orb_service_version"] = service.Version + host, pt, err := net.SplitHostPort(serviceNode.Address) + if err != nil { + return err + } - // Add node metadata to the service - for k, v := range node.Metadata { - metadata["orb_node_"+k] = v - } + if host == "" { + host = serviceNode.Address + } - // Add the transport scheme to metadata if required - if _, ok := metadata[metaTransportKey]; !ok { - metadata[metaTransportKey] = node.Transport - } + port, err := strconv.Atoi(pt) + if err != nil { + return err + } - // Add the node ID to metadata if required - if _, ok := metadata[metaNodeIDKey]; !ok { - metadata[metaNodeIDKey] = node.ID - } + metadata := map[string]string{} + // Add service metadata to the service + for k, v := range serviceNode.Metadata { + metadata[metaPrefix+k] = v + } - // register the service - asr := &consul.AgentServiceRegistration{ - ID: service.Name + "-" + node.ID + "-" + node.Transport, - Name: service.Name, - Tags: tags, - Port: port, - Address: host, - Meta: metadata, - Check: check, - } + // register the service + asr := &consul.AgentServiceRegistration{ + ID: nodeID(serviceNode), + Name: serviceNode.Name, + Port: port, + Address: host, + Meta: metadata, + Check: check, + } - // Specify consul connect - if c.config.Connect { - asr.Connect = &consul.AgentServiceConnect{ - Native: true, - } + // Specify consul connect + if c.config.Connect { + asr.Connect = &consul.AgentServiceConnect{ + Native: true, } + } - if err := c.Client().Agent().ServiceRegister(asr); err != nil { - return err - } + if err := c.Client().Agent().ServiceRegister(asr); err != nil { + return err + } - // if the TTL is 0 we don't mess with the checks - if options.TTL == time.Duration(0) { - continue - } + // if the TTL is 0 we don't mess with the checks + if serviceNode.TTL == time.Duration(0) { + return nil + } - // pass the healthcheck - if err := c.Client().Agent().PassTTL("service:"+node.ID+"-"+node.Transport, ""); err != nil { - return err - } + // pass the healthcheck + if err := c.Client().Agent().PassTTL("service:"+asr.ID, ""); err != nil { + return err } return nil @@ -247,10 +212,10 @@ func (c *RegistryConsul) Register(service *registry.Service, opts ...registry.Re // GetService returns a service from the registry. // -//nolint:funlen,gocyclo -func (c *RegistryConsul) GetService(name string, _ ...registry.GetOption) ([]*registry.Service, error) { +//nolint:gocyclo +func (c *RegistryConsul) GetService(ctx context.Context, namespace, region, name string, schemes []string) ([]registry.ServiceNode, error) { if c.config.Cache { - return c.cache.GetService(name) + return c.cache.GetService(ctx, namespace, region, name, schemes) } var ( @@ -270,44 +235,41 @@ func (c *RegistryConsul) GetService(name string, _ ...registry.GetOption) ([]*re } if len(rsp) == 0 { - return []*registry.Service{}, registry.ErrNotFound + return []registry.ServiceNode{}, registry.ErrNotFound } - var ( - haveService bool - svc *registry.Service - ) - - serviceMap := make(map[string]*registry.Service) + services := []registry.ServiceNode{} for _, node := range rsp { if node.Service.Service != name { - c.logger.Warn("Service name does not match", "name", name, "service", node.Service.Service) continue } - // version is now a tag - version, _ := decodeVersion(node.Service.Tags) + serviceNode, err := idToNode(node.Service.ID) + if err != nil { + continue + } - nodeMeta := map[string]string{} svcMeta := map[string]string{} for k, v := range node.Service.Meta { - if strings.HasPrefix(k, "orb_service_") { - svcMeta[strings.TrimPrefix(k, "orb_service_")] = v - } else if strings.HasPrefix(k, "orb_node_") { - nodeMeta[strings.TrimPrefix(k, "orb_node_")] = v + if strings.HasPrefix(k, metaPrefix) { + svcMeta[strings.TrimPrefix(k, metaPrefix)] = v } } - svc, haveService = serviceMap[version] - if !haveService { - svc = ®istry.Service{ - Endpoints: decodeEndpoints(node.Service.Tags), - Name: node.Service.Service, - Version: version, - Metadata: svcMeta, - } + serviceNode.Metadata = svcMeta + + if serviceNode.Namespace != namespace { + continue + } + + if serviceNode.Region != region { + continue + } + + if len(schemes) > 0 && !slices.Contains(schemes, serviceNode.Scheme) { + continue } var del bool @@ -325,45 +287,16 @@ func (c *RegistryConsul) GetService(name string, _ ...registry.GetOption) ([]*re continue } - rNode := ®istry.Node{ - ID: node.Node.ID, - Address: maddr.HostPort(node.Node.Address, node.Service.Port), - Metadata: nodeMeta, - } - - // Extract the transport from Metadata - if transport, ok := node.Service.Meta[metaTransportKey]; ok { - rNode.Transport = transport - delete(rNode.Metadata, metaTransportKey) - } else { - continue - } - - // Extract the node ID from Metadata - if nodeID, ok := node.Service.Meta[metaNodeIDKey]; ok { - rNode.ID = nodeID - delete(rNode.Metadata, metaNodeIDKey) - } else { - continue - } - - serviceMap[version] = svc - svc.Nodes = append(svc.Nodes, rNode) - } - - var services []*registry.Service //nolint:prealloc - - for _, svc := range serviceMap { - services = append(services, svc) + services = append(services, serviceNode) } return services, nil } // ListServices lists services within the registry. -func (c *RegistryConsul) ListServices(_ ...registry.ListOption) ([]*registry.Service, error) { +func (c *RegistryConsul) ListServices(ctx context.Context, namespace, region string, schemes []string) ([]registry.ServiceNode, error) { if c.config.Cache { - return c.cache.ListServices() + return c.cache.ListServices(ctx, namespace, region, schemes) } rsp, _, err := c.Client().Catalog().Services(c.queryOptions) @@ -371,24 +304,26 @@ func (c *RegistryConsul) ListServices(_ ...registry.ListOption) ([]*registry.Ser return nil, err } - services := map[string]*registry.Service{} + var nodes []registry.ServiceNode for service := range rsp { - svcs, err := c.GetService(service) + srvNodes, err := c.GetService(ctx, namespace, region, service, schemes) if err != nil { + if errors.Is(err, registry.ErrNotFound) { + continue + } + return nil, err } - for _, svc := range svcs { - services[svc.Name+"-"+svc.Version] = svc - } + nodes = append(nodes, srvNodes...) } - return slices.Collect(maps.Values(services)), nil + return nodes, nil } // Watch returns a Watcher which you can watch on. -func (c *RegistryConsul) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { +func (c *RegistryConsul) Watch(_ context.Context, opts ...registry.WatchOption) (registry.Watcher, error) { return newConsulWatcher(c, opts...) } @@ -429,8 +364,6 @@ func (c *RegistryConsul) Client() *consul.Client { // Provide creates a new Consul registry. func Provide( - name string, - version string, datas map[string]any, _ *types.Components, logger log.Logger, @@ -443,17 +376,16 @@ func Provide( } // Return the new registry. - reg := New(name, version, cfg, logger) + reg := New(cfg, logger) return registry.Type{Registry: reg}, nil } // New creates a new consul registry. -func New(serviceName string, _ string, cfg Config, logger log.Logger) *RegistryConsul { +func New(cfg Config, logger log.Logger) *RegistryConsul { cRegistry := &RegistryConsul{ - serviceName: serviceName, - config: cfg, - logger: logger, + config: cfg, + logger: logger, queryOptions: &consul.QueryOptions{ AllowStale: true, }, diff --git a/registry/consul/consul_test.go b/registry/consul/consul_test.go index a9cd0192..d0bf6032 100644 --- a/registry/consul/consul_test.go +++ b/registry/consul/consul_test.go @@ -19,7 +19,7 @@ import ( "github.com/go-orb/plugins/registry/tests" ) -func createServer() (*tests.TestSuite, func() error, error) { +func createSuite() (*tests.TestSuite, func() error, error) { ctx := context.Background() logger, err := log.New(log.WithLevel("TRACE")) @@ -28,42 +28,37 @@ func createServer() (*tests.TestSuite, func() error, error) { return nil, func() error { return nil }, err } - server, err := createServer1(&testing.T{}) + server, err := createServer(&testing.T{}) if err != nil { logger.Error("failed to create a consul server", "err", err) return nil, func() error { return nil }, err } - reg1 := New("test1.service", "", NewConfig(WithAddress(server.HTTPAddr)), logger) + reg1 := New(NewConfig(WithAddress(server.HTTPAddr), WithNoCache()), logger) if err := reg1.Start(ctx); err != nil { log.Error("failed to connect registry one to Consul server", "err", err) server.Stop() //nolint:errcheck return nil, func() error { return nil }, err } - reg2 := New("test2.service", "", NewConfig(WithAddress(server.HTTPAddr)), logger) + reg2 := New(NewConfig(WithAddress(server.HTTPAddr)), logger) if err := reg2.Start(ctx); err != nil { log.Error("failed to connect registry two to Consul server", "err", err) server.Stop() //nolint:errcheck return nil, func() error { return nil }, err } - reg3 := New("test3.service", "", NewConfig(WithAddress(server.HTTPAddr)), logger) - if err := reg3.Start(ctx); err != nil { - log.Error("failed to connect registry three to Consul server", "err", err) - server.Stop() //nolint:errcheck - return nil, func() error { return nil }, err - } - cleanup := func() error { - _ = server.Stop() //nolint:errcheck + _ = reg1.Stop(ctx) //nolint:errcheck + _ = reg2.Stop(ctx) //nolint:errcheck + _ = server.Stop() //nolint:errcheck return nil } - return tests.CreateSuite(logger, []registry.Registry{reg1, reg2, reg3}, time.Millisecond*200, 0), cleanup, nil + return tests.CreateSuite(logger, []registry.Registry{reg1, reg2}, time.Millisecond*500), cleanup, nil } -func createServer1(tb testing.TB) (*testutil.TestServer, error) { +func createServer(tb testing.TB) (*testutil.TestServer, error) { tb.Helper() // Compile our consul path. @@ -90,7 +85,7 @@ func createServer1(tb testing.TB) (*testutil.TestServer, error) { } func TestSuite(t *testing.T) { - s, cleanup, err := createServer() + s, cleanup, err := createSuite() require.NoError(t, err, "while creating a server") // Run the tests. @@ -100,7 +95,7 @@ func TestSuite(t *testing.T) { } func BenchmarkGetService(b *testing.B) { - s, cleanup, err := createServer() + s, cleanup, err := createSuite() require.NoError(b, err, "while creating a server") s.BenchmarkGetService(b) @@ -109,7 +104,7 @@ func BenchmarkGetService(b *testing.B) { } func BenchmarkParallelGetService(b *testing.B) { - s, cleanup, err := createServer() + s, cleanup, err := createSuite() require.NoError(b, err, "while creating a server") s.BenchmarkGetService(b) @@ -118,7 +113,7 @@ func BenchmarkParallelGetService(b *testing.B) { } func BenchmarkGetServiceWithNoNodes(b *testing.B) { - s, cleanup, err := createServer() + s, cleanup, err := createSuite() require.NoError(b, err, "while creating a server") s.BenchmarkGetServiceWithNoNodes(b) diff --git a/registry/consul/encoding.go b/registry/consul/encoding.go index 2fe3f8f6..a8132084 100644 --- a/registry/consul/encoding.go +++ b/registry/consul/encoding.go @@ -4,10 +4,7 @@ import ( "bytes" "compress/zlib" "encoding/hex" - "encoding/json" "io" - - "github.com/go-orb/go-orb/registry" ) func encode(buf []byte) string { @@ -48,60 +45,6 @@ func decode(d string) []byte { return rbuf } -func encodeEndpoints(en []*registry.Endpoint) []string { - var tags []string - - for _, e := range en { - if b, err := json.Marshal(e); err == nil { - tags = append(tags, "e-"+encode(b)) - } - } - - return tags -} - -func decodeEndpoints(tags []string) []*registry.Endpoint { - var endpoint []*registry.Endpoint - - // use the first format you find - var ver byte - - for _, tag := range tags { - if len(tag) == 0 || tag[0] != 'e' { - continue - } - - // check version - if ver > 0 && tag[1] != ver { - continue - } - - var ( - e *registry.Endpoint - buf []byte - ) - - // Old encoding was plain - if tag[1] == '=' { - buf = []byte(tag[2:]) - } - - // New encoding is hex - if tag[1] == '-' { - buf = decode(tag[2:]) - } - - if err := json.Unmarshal(buf, &e); err == nil { - endpoint = append(endpoint, e) - } - - // set version - ver = tag[1] - } - - return endpoint -} - func encodeVersion(v string) []string { return []string{"v-" + encode([]byte(v))} } diff --git a/registry/consul/encoding_test.go b/registry/consul/encoding_test.go index 073b7ed1..a2207dc9 100644 --- a/registry/consul/encoding_test.go +++ b/registry/consul/encoding_test.go @@ -1,115 +1,9 @@ package consul import ( - "encoding/json" "testing" - - "github.com/go-orb/go-orb/registry" ) -func TestEncodingEndpoints(t *testing.T) { - eps := []*registry.Endpoint{ - { - Name: "endpoint1", - Request: ®istry.Value{ - Name: "request", - Type: "request", - }, - Response: ®istry.Value{ - Name: "response", - Type: "response", - }, - Metadata: map[string]string{ - "foo1": "bar1", - }, - }, - { - Name: "endpoint2", - Request: ®istry.Value{ - Name: "request", - Type: "request", - }, - Response: ®istry.Value{ - Name: "response", - Type: "response", - }, - Metadata: map[string]string{ - "foo2": "bar2", - }, - }, - { - Name: "endpoint3", - Request: ®istry.Value{ - Name: "request", - Type: "request", - }, - Response: ®istry.Value{ - Name: "response", - Type: "response", - }, - Metadata: map[string]string{ - "foo3": "bar3", - }, - }, - } - - testEp := func(ep *registry.Endpoint, enc string) { - // encode endpoint - e := encodeEndpoints([]*registry.Endpoint{ep}) - - // check there are two tags; old and new - if len(e) != 1 { - t.Fatalf("Expected 1 encoded tags, got %v", e) - } - - // check old encoding - var seen bool - - for _, en := range e { - if en == enc { - seen = true - break - } - } - - if !seen { - t.Fatalf("Expected %s but not found", enc) - } - - // decode - d := decodeEndpoints([]string{enc}) - if len(d) == 0 { - t.Fatalf("Expected %v got %v", ep, d) - } - - // check name - if d[0].Name != ep.Name { - t.Fatalf("Expected ep %s got %s", ep.Name, d[0].Name) - } - - // check all the metadata exists - for k, v := range ep.Metadata { - if gv := d[0].Metadata[k]; gv != v { - t.Fatalf("Expected key %s val %s got val %s", k, v, gv) - } - } - } - - for _, ep := range eps { - // JSON encoded - jencoded, err := json.Marshal(ep) - if err != nil { - t.Fatal(err) - } - - // HEX encoded - hencoded := encode(jencoded) - // endpoint tag - hepTag := "e-" + hencoded - testEp(ep, hepTag) - } -} - func TestEncodingVersion(t *testing.T) { testData := []struct { decoded string diff --git a/registry/consul/go.mod b/registry/consul/go.mod index e89dc833..3834034f 100644 --- a/registry/consul/go.mod +++ b/registry/consul/go.mod @@ -3,15 +3,14 @@ module github.com/go-orb/plugins/registry/consul go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/google/uuid v1.6.0 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122813-09813c7b9d65 github.com/hashicorp/consul/api v1.31.2 github.com/hashicorp/consul/sdk v0.16.2 - github.com/hashicorp/go-multierror v1.1.1 + github.com/hashicorp/go-hclog v1.6.3 github.com/stretchr/testify v1.10.0 ) @@ -23,9 +22,9 @@ require ( github.com/fatih/color v1.18.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-metrics v0.5.4 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.7.0 // indirect @@ -34,7 +33,7 @@ require ( github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/miekg/dns v1.1.63 // indirect + github.com/miekg/dns v1.1.64 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pkg/errors v0.9.1 // indirect diff --git a/registry/consul/go.sum b/registry/consul/go.sum index 55a9e7b2..90b151bd 100644 --- a/registry/consul/go.sum +++ b/registry/consul/go.sum @@ -31,16 +31,16 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 h1:X3NixTLN7+Oqn674kP8t96ztHUspl1CEliCY1bD8Kzk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:w2LKGIQfvocVKtQPmxoGi36ND4cKXicVlfpORu3Irjs= -github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250320235901-3af29c3a3b34 h1:/EISsTJZF9tedAI3PKEFmz4LlIgEVSe+bRELz1piw/c= -github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:fllOPue/7Gy6Aebxmiz6jjZd69nZdYwFewf5clQ+u24= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320235901-3af29c3a3b34 h1:LV9i2413Zr0kkoaNrEJB+uMEu5MXqt+IOL3BUwPq6mo= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:C2DhKbnImH0vAc4+iyLcY0fADmBaIJ2y1u8MxmQSkpw= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 h1:Fj2tX19g5TxjS9pHyDV4ZMLkZYW4cuNJ6yh149HRJ84= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:U4rbrSlCGhQaiJxl4GRwIQLUv+Cg8og9NEEInd9j8ww= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 h1:6pxnS4Kg1WRSMKU2DFVl40EFlO06YT7gT/d0uK8ZEB4= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:VLPoWEGe+/gcCUZnp3/WJXBP35C22+14CmjrIZegfQY= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122813-09813c7b9d65 h1:InnSP/542m8MeczOjL14qtnpeGu14od2PAtedfRPrg8= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:qUq39uHPQ6qZZxNFtH3IPb01vWESqwSJrzUvrzAiBzc= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -63,8 +63,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/consul/api v1.31.2 h1:NicObVJHcCmyOIl7Z9iHPvvFrocgTYo9cITSGg0/7pw= github.com/hashicorp/consul/api v1.31.2/go.mod h1:Z8YgY0eVPukT/17ejW+l+C7zJmKwgPHtjU1q16v/Y40= github.com/hashicorp/consul/sdk v0.16.2 h1:cGX/djeEe9r087ARiKVWwVWCF64J+yW0G6ftZMZYbj0= @@ -130,8 +128,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= -github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= +github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ= +github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= diff --git a/registry/consul/watcher.go b/registry/consul/watcher.go index f5e5a889..d67f4cf6 100644 --- a/registry/consul/watcher.go +++ b/registry/consul/watcher.go @@ -1,14 +1,14 @@ package consul import ( + "maps" "strings" "sync" "github.com/go-orb/go-orb/registry" - maddr "github.com/go-orb/go-orb/util/addr" - "github.com/go-orb/plugins/registry/regutil" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api/watch" + "github.com/hashicorp/go-hclog" ) var _ registry.Watcher = (*consulWatcher)(nil) @@ -23,7 +23,7 @@ type consulWatcher struct { exit chan bool sync.RWMutex - services map[string][]*registry.Service + nodes map[string]registry.ServiceNode } func newConsulWatcher(regConsul *RegistryConsul, opts ...registry.WatchOption) (*consulWatcher, error) { @@ -38,12 +38,12 @@ func newConsulWatcher(regConsul *RegistryConsul, opts ...registry.WatchOption) ( exit: make(chan bool), next: make(chan *registry.Result, 10), watchers: make(map[string]*watch.Plan), - services: make(map[string][]*registry.Service), + nodes: make(map[string]registry.ServiceNode), } // If a specific service is provided, watch that service if len(wo.Service) > 0 { - wp, err := watch.Parse(map[string]interface{}{ + wp, err := watch.Parse(map[string]any{ "service": wo.Service, "type": "service", }) @@ -51,29 +51,29 @@ func newConsulWatcher(regConsul *RegistryConsul, opts ...registry.WatchOption) ( return nil, err } + wp.Logger = hclog.New(&hclog.LoggerOptions{Level: hclog.Off}) wp.Handler = watcher.handle - tmp := func() { + go func() { _ = wp.RunWithClientAndHclog(regConsul.Client(), wp.Logger) //nolint:errcheck - } - go tmp() + }() watcher.wp = wp } else { // If no service name is specified, watch all services - wp, err := watch.Parse(map[string]interface{}{ + wp, err := watch.Parse(map[string]any{ "type": "services", }) if err != nil { return nil, err } + wp.Logger = hclog.New(&hclog.LoggerOptions{Level: hclog.Off}) wp.Handler = watcher.handle - tmp := func() { + go func() { _ = wp.RunWithClientAndHclog(regConsul.Client(), wp.Logger) //nolint:errcheck - } - go tmp() + }() watcher.wp = wp } @@ -81,173 +81,107 @@ func newConsulWatcher(regConsul *RegistryConsul, opts ...registry.WatchOption) ( return watcher, nil } -//nolint:funlen,gocognit,gocyclo,cyclop -func (cw *consulWatcher) serviceHandler(_ uint64, data interface{}) { - entries, ok := data.([]*api.ServiceEntry) - if !ok { +func (cw *consulWatcher) serviceHandler(_ uint64, data any) { + entries, entriesOk := data.([]*api.ServiceEntry) + if !entriesOk { return } - var ( - haveService bool - svc *registry.Service - ) - - serviceMap := make(map[string]*registry.Service) - serviceName := "" + serviceNodes := make(map[string]registry.ServiceNode, len(entries)) + servicePrefix := "" for _, node := range entries { - // version is now a tag - version, _ := decodeVersion(node.Service.Tags) - - nodeMeta := map[string]string{} svcMeta := map[string]string{} for k, v := range node.Service.Meta { - if strings.HasPrefix(k, "orb_service_") { - svcMeta[strings.TrimPrefix(k, "orb_service_")] = v - } else if strings.HasPrefix(k, "orb_node_") { - nodeMeta[strings.TrimPrefix(k, "orb_node_")] = v + if strings.HasPrefix(k, metaPrefix) { + svcMeta[strings.TrimPrefix(k, metaPrefix)] = v } } - // Skip unknown services. - if len(nodeMeta) == 0 && len(svcMeta) == 0 { + // Try to parse the node ID to get the service node + serviceNode, err := idToNode(node.Service.ID) + if err != nil { continue } - svc, haveService = serviceMap[version] - if !haveService { - serviceName = node.Service.Service - svc = ®istry.Service{ - Endpoints: decodeEndpoints(node.Service.Tags), - Name: node.Service.Service, - Version: svcMeta["version"], - Metadata: svcMeta, - } - } - - var del bool + // Update with the latest metadata + serviceNode.Metadata = svcMeta - for _, check := range node.Checks { - // delete the node if the status is critical - if check.Status == "critical" { - del = true - break - } - } - - // if delete then skip the node - if del { - continue + if servicePrefix == "" { + servicePrefix = idToPrefix(node.Service.ID) } - rNode := ®istry.Node{ - ID: node.Node.ID, - Address: maddr.HostPort(node.Node.Address, node.Service.Port), - Metadata: nodeMeta, - } - - // Extract the transport from Metadata - if transport, ok := node.Service.Meta[metaTransportKey]; ok { - rNode.Transport = transport - delete(rNode.Metadata, metaTransportKey) - } else { - continue - } - - // Extract the node ID from Metadata - if nodeID, ok := node.Service.Meta[metaNodeIDKey]; ok { - rNode.ID = nodeID - delete(rNode.Metadata, metaNodeIDKey) - } else { - continue - } - - serviceMap[version] = svc - svc.Nodes = append(svc.Nodes, rNode) + serviceNodes[node.Service.ID] = serviceNode } + // Get a copy of the current services cw.RLock() - // make a copy - rservices := make(map[string][]*registry.Service) - for k, v := range cw.services { - rservices[k] = v - } + currentNodes := make(map[string]registry.ServiceNode) + maps.Copy(currentNodes, cw.nodes) cw.RUnlock() - var newServices []*registry.Service //nolint:prealloc + // Check for new nodes. + for id, newNode := range serviceNodes { + oldNode, entriesOk := currentNodes[id] + if !entriesOk { + cw.next <- ®istry.Result{Action: registry.Create, Node: newNode} - // serviceMap is the new set of services keyed by name+version - for _, newService := range serviceMap { - // append to the new set of cached services - newServices = append(newServices, newService) + // Update the current nodes + cw.Lock() + cw.nodes[id] = newNode + cw.Unlock() + } else if !metadataEqual(oldNode.Metadata, newNode.Metadata) { + // Check for updates + cw.next <- ®istry.Result{Action: registry.Update, Node: newNode} - // check if the service exists in the existing cache - oldServices, ok := rservices[serviceName] - if !ok { - // does not exist? then we're creating brand new entries - cw.next <- ®istry.Result{Action: "create", Service: newService} - continue + // Update the current nodes + cw.Lock() + cw.nodes[id] = newNode + cw.Unlock() } + } - // service exists. ok let's figure out what to update and delete version wise - action := "create" - - for _, oldService := range oldServices { - // does this version exist? - // no? then default to create - if oldService.Version != newService.Version { - continue - } + if servicePrefix == "" { + return + } - // yes? then it's an update - action = "update" + oldNodes := make(map[string]registry.ServiceNode) - var nodes []*registry.Node - // check the old nodes to see if they've been deleted - for _, oldNode := range oldService.Nodes { - var seen bool + // Check for deleted nodes + for k, v := range currentNodes { + if strings.HasPrefix(k, servicePrefix) { + oldNodes[k] = v + } + } - for _, newNode := range newService.Nodes { - if newNode.ID == oldNode.ID { - seen = true - break - } - } - // does the old node exist in the new set of nodes - // no? then delete that shit - if !seen { - nodes = append(nodes, oldNode) - } - } + for id, oldNode := range oldNodes { + if _, exists := serviceNodes[id]; !exists { + cw.next <- ®istry.Result{Action: registry.Delete, Node: oldNode} - // it's an update rather than creation - if len(nodes) > 0 { - delService := regutil.CopyService(oldService) - delService.Nodes = nodes - cw.next <- ®istry.Result{Action: "delete", Service: delService} - } + cw.Lock() + delete(cw.nodes, id) + cw.Unlock() } + } +} - cw.next <- ®istry.Result{Action: action, Service: newService} +// Helper function to compare metadata. +func metadataEqual(a, b map[string]string) bool { + if len(a) != len(b) { + return false } - // Now check old versions that may not be in new services map - for _, old := range rservices[serviceName] { - // old version does not exist in new version map - // kill it with fire! - if _, ok := serviceMap[old.Version]; !ok { - cw.next <- ®istry.Result{Action: "delete", Service: old} + for k, v := range a { + if bv, ok := b[k]; !ok || bv != v { + return false } } - cw.Lock() - cw.services[serviceName] = newServices - cw.Unlock() + return true } -func (cw *consulWatcher) handle(_ uint64, data interface{}) { +func (cw *consulWatcher) handle(_ uint64, data any) { services, ok := data.(map[string][]string) if !ok { return @@ -265,56 +199,38 @@ func (cw *consulWatcher) handle(_ uint64, data interface{}) { continue } - wp, err := watch.Parse(map[string]interface{}{ + wp, err := watch.Parse(map[string]any{ "type": "service", "service": service, }) if err == nil { + wp.Logger = hclog.New(&hclog.LoggerOptions{Level: hclog.Off}) wp.Handler = cw.serviceHandler - tmp := func() { + go func() { _ = wp.RunWithClientAndHclog(cw.r.Client(), wp.Logger) //nolint:errcheck - } - go tmp() + }() cw.watchers[service] = wp - } - } - cw.RLock() - // make a copy - rservices := make(map[string][]*registry.Service) - for k, v := range cw.services { - rservices[k] = v + continue + } } - cw.RUnlock() // remove unknown services from registry - // save the things we want to delete - deleted := make(map[string][]*registry.Service) + for k := range cw.watchers { + if _, ok := services[k]; !ok { + delete(cw.watchers, k) - for service := range rservices { - if _, ok := services[service]; !ok { cw.Lock() - // save this before deleting - deleted[service] = cw.services[service] - delete(cw.services, service) - cw.Unlock() - } - } - - // remove unknown services from watchers - for service, w := range cw.watchers { - if _, ok := services[service]; !ok { - w.Stop() - delete(cw.watchers, service) - - for _, oldService := range deleted[service] { - // send a delete for the service nodes that we're removing - cw.next <- ®istry.Result{Action: "delete", Service: oldService} + for id, node := range cw.nodes { + if _, _, name := splitID(id); name == k { + cw.next <- ®istry.Result{Action: registry.Delete, Node: node} + delete(cw.nodes, id) + } } - // sent the empty list as the last resort to indicate to delete the entire service - cw.next <- ®istry.Result{Action: "delete", Service: ®istry.Service{Name: service}} + + cw.Unlock() } } } @@ -323,11 +239,7 @@ func (cw *consulWatcher) Next() (*registry.Result, error) { select { case <-cw.exit: return nil, registry.ErrWatcherStopped - case r, ok := <-cw.next: - if !ok { - return nil, registry.ErrWatcherStopped - } - + case r := <-cw.next: return r, nil } } @@ -337,21 +249,17 @@ func (cw *consulWatcher) Stop() error { case <-cw.exit: return nil default: - close(cw.exit) - - if cw.wp == nil { - return nil + // stop the watchers + for _, wp := range cw.watchers { + wp.Stop() } - cw.wp.Stop() - - // drain results - for { - select { - case <-cw.next: - default: - return nil - } + if cw.wp != nil { + cw.wp.Stop() } + + close(cw.exit) } + + return nil } diff --git a/registry/kvstore/go.mod b/registry/kvstore/go.mod index ef2a3b30..df82d05b 100644 --- a/registry/kvstore/go.mod +++ b/registry/kvstore/go.mod @@ -3,14 +3,12 @@ module github.com/go-orb/plugins/registry/kvstore go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/kvstore/natsjs v0.0.0-20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/google/uuid v1.6.0 - github.com/hashicorp/go-multierror v1.1.1 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/kvstore/natsjs v0.0.0-20250324122813-09813c7b9d65 + github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122813-09813c7b9d65 github.com/nats-io/nats-server/v2 v2.10.26 github.com/stretchr/testify v1.10.0 ) @@ -19,7 +17,6 @@ require ( dario.cat/mergo v1.0.1 // indirect github.com/cornelk/hashmap v1.0.8 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect github.com/klauspost/compress v1.18.0 // indirect github.com/kr/text v0.2.0 // indirect github.com/minio/highwayhash v1.0.3 // indirect diff --git a/registry/kvstore/go.sum b/registry/kvstore/go.sum index 16bf175b..65a2d9e6 100644 --- a/registry/kvstore/go.sum +++ b/registry/kvstore/go.sum @@ -5,25 +5,18 @@ github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2L github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= -github.com/go-orb/plugins/kvstore/natsjs v0.0.0-20250320235901-3af29c3a3b34 h1:UITXn5ryhxgtHGcVJ222RrvWsIRyOdhp6xyeNusoG9s= -github.com/go-orb/plugins/kvstore/natsjs v0.0.0-20250320235901-3af29c3a3b34/go.mod h1:MLRHZy7j8WaYIbZurf1A/GQwndaOs4h9y6yVA5xnrck= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 h1:X3NixTLN7+Oqn674kP8t96ztHUspl1CEliCY1bD8Kzk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:w2LKGIQfvocVKtQPmxoGi36ND4cKXicVlfpORu3Irjs= -github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250320235901-3af29c3a3b34 h1:/EISsTJZF9tedAI3PKEFmz4LlIgEVSe+bRELz1piw/c= -github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:fllOPue/7Gy6Aebxmiz6jjZd69nZdYwFewf5clQ+u24= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320235901-3af29c3a3b34 h1:LV9i2413Zr0kkoaNrEJB+uMEu5MXqt+IOL3BUwPq6mo= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:C2DhKbnImH0vAc4+iyLcY0fADmBaIJ2y1u8MxmQSkpw= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/kvstore/natsjs v0.0.0-20250324122813-09813c7b9d65 h1:xII5JMxM+uEgRIvw6M+FEvxaYiHEOjF9632/bfd+AGM= +github.com/go-orb/plugins/kvstore/natsjs v0.0.0-20250324122813-09813c7b9d65/go.mod h1:Uoc9J4khEzaKxLiftCsIYEtxdn8+EX3+e/HBPUgMWxc= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 h1:Fj2tX19g5TxjS9pHyDV4ZMLkZYW4cuNJ6yh149HRJ84= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:U4rbrSlCGhQaiJxl4GRwIQLUv+Cg8og9NEEInd9j8ww= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 h1:6pxnS4Kg1WRSMKU2DFVl40EFlO06YT7gT/d0uK8ZEB4= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:VLPoWEGe+/gcCUZnp3/WJXBP35C22+14CmjrIZegfQY= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122813-09813c7b9d65 h1:InnSP/542m8MeczOjL14qtnpeGu14od2PAtedfRPrg8= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:qUq39uHPQ6qZZxNFtH3IPb01vWESqwSJrzUvrzAiBzc= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= diff --git a/registry/kvstore/kvstore.go b/registry/kvstore/kvstore.go index 860081e5..64531de6 100644 --- a/registry/kvstore/kvstore.go +++ b/registry/kvstore/kvstore.go @@ -4,6 +4,8 @@ package kvstore import ( "context" "errors" + "slices" + "strings" "github.com/go-orb/go-orb/codecs" "github.com/go-orb/go-orb/config" @@ -13,10 +15,35 @@ import ( "github.com/go-orb/go-orb/types" "github.com/go-orb/go-orb/util/orberrors" "github.com/go-orb/plugins/registry/regutil/cache" - "github.com/google/uuid" - "github.com/hashicorp/go-multierror" ) +func nodeKey(s registry.ServiceNode, delimiter string) string { + return strings.Join([]string{ + s.Namespace, + s.Region, + s.Name, + s.Version, + s.Scheme, + s.Address, + }, delimiter) +} + +func keyToServiceNode(key string, delimiter string) (registry.ServiceNode, error) { + parts := strings.Split(key, delimiter) + if len(parts) != 6 { + return registry.ServiceNode{}, errors.New("invalid key format") + } + + return registry.ServiceNode{ + Namespace: parts[0], + Region: parts[1], + Name: parts[2], + Version: parts[3], + Scheme: parts[4], + Address: parts[5], + }, nil +} + // This is here to make sure Registry implements registry.Registry. var _ registry.Registry = (*Registry)(nil) @@ -24,15 +51,10 @@ var _ registry.Registry = (*Registry)(nil) type Registry struct { ctx context.Context - serviceName string - serviceVersion string - codec codecs.Marshaler config Config - id string - logger log.Logger kvstore kvstore.Type @@ -41,27 +63,6 @@ type Registry struct { cache *cache.Cache } -// ServiceName returns the configured name of this service. -func (c *Registry) ServiceName() string { - return c.serviceName -} - -// ServiceVersion returns the configured version of this service. -func (c *Registry) ServiceVersion() string { - return c.serviceVersion -} - -// NodeID returns the ID of this service node in the registry. -func (c *Registry) NodeID() string { - if c.id != "" { - return c.id - } - - c.id = uuid.New().String() - - return c.id -} - // Start starts the registry. func (c *Registry) Start(ctx context.Context) error { c.ctx = ctx @@ -103,61 +104,62 @@ func (c *Registry) Type() string { } // Deregister deregisters a service within the registry. -func (c *Registry) Deregister(s *registry.Service, _ ...registry.DeregisterOption) error { - mErr := &multierror.Error{} - - for _, node := range s.Nodes { - key := s.Name + c.config.ServiceDelimiter + node.ID + c.config.ServiceDelimiter + s.Version - c.logger.Trace("deregistering service", "service", s, "key", key) +func (c *Registry) Deregister(_ context.Context, serviceNode registry.ServiceNode) error { + key := nodeKey(serviceNode, c.config.ServiceDelimiter) + c.logger.Trace("deregistering service", "serviceNode", serviceNode, "key", key) - mErr = multierror.Append(mErr, c.kvstore.Purge(key, c.config.Database, c.config.Table)) - } - - return mErr.ErrorOrNil() + return c.kvstore.Purge(key, c.config.Database, c.config.Table) } // Register registers a service within the registry. -func (c *Registry) Register(service *registry.Service, _ ...registry.RegisterOption) error { - if service == nil { - return orberrors.ErrBadRequest.Wrap(errors.New("wont store nil service")) +func (c *Registry) Register(_ context.Context, serviceNode registry.ServiceNode) error { + if serviceNode.Name == "" { + return orberrors.ErrBadRequest.Wrap(errors.New("won't store service with empty name")) } - mErr := &multierror.Error{} - - for _, node := range service.Nodes { - key := service.Name + c.config.ServiceDelimiter + node.ID + c.config.ServiceDelimiter + service.Version - c.logger.Trace("registering service", "service", service, "key", key) + key := nodeKey(serviceNode, c.config.ServiceDelimiter) + c.logger.Trace("registering service", "serviceNode", serviceNode, "key", key) - mService := ®istry.Service{ - Name: service.Name, - Version: service.Version, - Metadata: service.Metadata, - Endpoints: service.Endpoints, - Nodes: []*registry.Node{node}, - } - - b, err := c.codec.Marshal(mService) - if err != nil { - return orberrors.ErrInternalServerError.Wrap(err) - } - - mErr = multierror.Append(mErr, c.kvstore.Set(key, c.config.Database, c.config.Table, b)) + b, err := c.codec.Marshal(serviceNode) + if err != nil { + return orberrors.ErrInternalServerError.Wrap(err) } - return mErr.ErrorOrNil() + return c.kvstore.Set(key, c.config.Database, c.config.Table, b) } // GetService returns a service from the registry. -func (c *Registry) GetService(name string, opts ...registry.GetOption) ([]*registry.Service, error) { +func (c *Registry) GetService(ctx context.Context, namespace, region, name string, schemes []string) ([]registry.ServiceNode, error) { if c.config.Cache { - return c.cache.GetService(name, opts...) + return c.cache.GetService(ctx, namespace, region, name, schemes) } - services, err := c.listServices(kvstore.KeysPrefix(name + c.config.ServiceDelimiter)) + key := strings.Join([]string{ + namespace, + region, + name, + }, c.config.ServiceDelimiter) + + key += c.config.ServiceDelimiter + + services, err := c.listServices(ctx, kvstore.KeysPrefix(key)) if err != nil { return nil, err } + // Filter by schemes if specified + if len(schemes) > 0 { + var filtered []registry.ServiceNode + + for _, service := range services { + if slices.Contains(schemes, service.Scheme) { + filtered = append(filtered, service) + } + } + + services = filtered + } + // If no services found, return ErrNotFound if len(services) == 0 { return nil, registry.ErrNotFound @@ -167,30 +169,58 @@ func (c *Registry) GetService(name string, opts ...registry.GetOption) ([]*regis } // ListServices lists services within the registry. -func (c *Registry) ListServices(opts ...registry.ListOption) ([]*registry.Service, error) { +func (c *Registry) ListServices(ctx context.Context, namespace, region string, schemes []string) ([]registry.ServiceNode, error) { if c.config.Cache { - return c.cache.ListServices(opts...) + return c.cache.ListServices(ctx, namespace, region, schemes) } - return c.listServices() + key := strings.Join([]string{ + namespace, + region, + }, c.config.ServiceDelimiter) + + key += c.config.ServiceDelimiter + + services, err := c.listServices(ctx, kvstore.KeysPrefix(key)) + if err != nil { + return nil, err + } + + // Filter by schemes if specified + if len(schemes) > 0 { + var filtered []registry.ServiceNode + + for _, service := range services { + if slices.Contains(schemes, service.Scheme) { + filtered = append(filtered, service) + } + } + + services = filtered + } + + return services, nil } // Watch returns a Watcher which you can watch on. -func (c *Registry) Watch(_ ...registry.WatchOption) (registry.Watcher, error) { +func (c *Registry) Watch(_ context.Context, _ ...registry.WatchOption) (registry.Watcher, error) { return NewWatcher(c) } -func (c *Registry) listServices(opts ...kvstore.KeysOption) ([]*registry.Service, error) { +func (c *Registry) listServices( + _ context.Context, + opts ...kvstore.KeysOption, +) ([]registry.ServiceNode, error) { keys, err := c.kvstore.Keys(c.config.Database, c.config.Table, opts...) if err != nil { return nil, err } - // Use name+version as the key for grouping services - serviceMap := map[string]*registry.Service{} + // Map to store unique service nodes + result := []registry.ServiceNode{} for _, k := range keys { - s, err := c.getNode(k) + svc, err := c.getNode(k) if err != nil { if errors.Is(err, registry.ErrNotFound) { // Skip not found errors and continue @@ -200,49 +230,33 @@ func (c *Registry) listServices(opts ...kvstore.KeysOption) ([]*registry.Service return nil, err } - // Create a unique key for this service name and version - key := s.Name + "-" + s.Version - - if serviceMap[key] == nil { - // First time seeing this service name+version - serviceMap[key] = s - } else { - // Add nodes to existing service entry - serviceMap[key].Nodes = append(serviceMap[key].Nodes, s.Nodes...) - } - } - - svcs := make([]*registry.Service, 0, len(serviceMap)) - for _, s := range serviceMap { - svcs = append(svcs, s) + result = append(result, svc) } - return svcs, nil + return result, nil } -// getNode retrieves a node from the store. It returns a service to also keep track of the version. -func (c *Registry) getNode(s string) (*registry.Service, error) { +// getNode retrieves a node from the store. +func (c *Registry) getNode(s string) (registry.ServiceNode, error) { recs, err := c.kvstore.Get(s, c.config.Database, c.config.Table) if err != nil { - return nil, err + return registry.ServiceNode{}, err } if len(recs) == 0 { - return nil, registry.ErrNotFound + return registry.ServiceNode{}, registry.ErrNotFound } - var svc registry.Service + var svc registry.ServiceNode if err := c.codec.Unmarshal(recs[0].Value, &svc); err != nil { - return nil, err + return registry.ServiceNode{}, err } - return &svc, nil + return svc, nil } // Provide creates a new memory registry. func Provide( - name string, - version string, datas map[string]any, _ *types.Components, logger log.Logger, @@ -269,15 +283,13 @@ func Provide( return registry.Type{}, err } - reg, err := New(name, version, cfg, logger, kvstore) + reg, err := New(cfg, logger, kvstore) return registry.Type{Registry: reg}, err } // New creates a new memory registry. func New( - serviceName string, - serviceVersion string, cfg Config, logger log.Logger, kvstore kvstore.Type, @@ -288,12 +300,10 @@ func New( } reg := &Registry{ - serviceName: serviceName, - serviceVersion: serviceVersion, - config: cfg, - logger: logger, - codec: codec, - kvstore: kvstore, + config: cfg, + logger: logger.With("component", "registry-kvstore"), + codec: codec, + kvstore: kvstore, } // Initialize the cache with a reference to this registry diff --git a/registry/kvstore/kvstore_test.go b/registry/kvstore/kvstore_test.go index 0adcf184..eb5e522c 100644 --- a/registry/kvstore/kvstore_test.go +++ b/registry/kvstore/kvstore_test.go @@ -19,7 +19,7 @@ import ( ) //nolint:unparam -func createRegistries(tb testing.TB) (*tests.TestSuite, func() error, error) { +func createSuite(tb testing.TB) (*tests.TestSuite, func() error, error) { tb.Helper() // Create context @@ -55,24 +55,18 @@ func createRegistries(tb testing.TB) (*tests.TestSuite, func() error, error) { err = store.Start(ctx) require.NoError(tb, err) - // Create first registry - cfg1 := NewConfig() - reg1, err := New("orb.service.test1", "1.0.0", cfg1, logger, kvstore.Type{KVStore: store}) + // Create first registry without caching + cfg1 := NewConfig(WithNoCache()) + reg1, err := New(cfg1, logger, kvstore.Type{KVStore: store}) require.NoError(tb, err) require.NoError(tb, reg1.Start(ctx)) - // Create second registry + // Create second registry with caching cfg2 := NewConfig() - reg2, err := New("orb.service.test2", "1.0.0", cfg2, logger, kvstore.Type{KVStore: store}) + reg2, err := New(cfg2, logger, kvstore.Type{KVStore: store}) require.NoError(tb, err) require.NoError(tb, reg2.Start(ctx)) - // Create third registry - cfg3 := NewConfig() - reg3, err := New("orb.service.test3", "1.0.0", cfg3, logger, kvstore.Type{KVStore: store}) - require.NoError(tb, err) - require.NoError(tb, reg3.Start(ctx)) - cleanup := func() error { cancel() @@ -80,17 +74,16 @@ func createRegistries(tb testing.TB) (*tests.TestSuite, func() error, error) { _ = reg1.Stop(ctx) //nolint:errcheck _ = reg2.Stop(ctx) //nolint:errcheck - _ = reg3.Stop(ctx) //nolint:errcheck _ = store.Stop(ctx) //nolint:errcheck server.Shutdown() return nil } - return tests.CreateSuite(logger, []registry.Registry{reg1, reg2, reg3}, time.Millisecond*200, 0), cleanup, nil + return tests.CreateSuite(logger, []registry.Registry{reg1, reg2}, time.Millisecond*200), cleanup, nil } func TestSuite(t *testing.T) { - s, cleanup, err := createRegistries(t) + s, cleanup, err := createSuite(t) require.NoError(t, err, "while creating a server") // Run the tests. @@ -100,7 +93,7 @@ func TestSuite(t *testing.T) { } func BenchmarkGetService(b *testing.B) { - s, cleanup, err := createRegistries(b) + s, cleanup, err := createSuite(b) require.NoError(b, err, "while creating a server") s.BenchmarkGetService(b) @@ -109,7 +102,7 @@ func BenchmarkGetService(b *testing.B) { } func BenchmarkParallelGetService(b *testing.B) { - s, cleanup, err := createRegistries(b) + s, cleanup, err := createSuite(b) if err != nil { b.Fatal("Error creating registries:", err) } @@ -120,7 +113,7 @@ func BenchmarkParallelGetService(b *testing.B) { } func BenchmarkGetServiceWithNoNodes(b *testing.B) { - s, cleanup, err := createRegistries(b) + s, cleanup, err := createSuite(b) require.NoError(b, err, "while creating a server") s.BenchmarkGetServiceWithNoNodes(b) diff --git a/registry/kvstore/watcher.go b/registry/kvstore/watcher.go index 8dd29cbc..a4f07fc6 100644 --- a/registry/kvstore/watcher.go +++ b/registry/kvstore/watcher.go @@ -2,7 +2,6 @@ package kvstore import ( "errors" - "strings" "github.com/go-orb/go-orb/codecs" "github.com/go-orb/go-orb/kvstore" @@ -50,20 +49,16 @@ func (w *Watcher) Next() (*registry.Result, error) { return nil, orberrors.ErrInternalServerError.Wrap(errors.New("watcher stopped")) } - var svc registry.Service + var svc registry.ServiceNode if kve.Value == nil { - // fake a service - parts := strings.SplitN(kve.Key, w.serviceDelimiter, 3) - if len(parts) != 3 { - return nil, orberrors.ErrBadRequest.Wrap(errors.New("invalid service key")) - } - - svc.Name = parts[0] + var err error - // go-orb registers nodes with a - separator - svc.Nodes = []*registry.Node{{ID: parts[1]}} - svc.Version = parts[2] + svc, err = keyToServiceNode(kve.Key, w.serviceDelimiter) + if err != nil { + _ = w.stop() //nolint:errcheck + return nil, orberrors.ErrBadRequest.Wrap(err) + } } else { if err := w.codec.Unmarshal(kve.Value, &svc); err != nil { _ = w.stop() //nolint:errcheck @@ -71,23 +66,23 @@ func (w *Watcher) Next() (*registry.Result, error) { } } - actionName := "" + var action registry.EventType switch kve.Operation { case kvstore.WatchOpCreate: - actionName = "create" + action = registry.Create case kvstore.WatchOpUpdate: - actionName = "update" + action = registry.Update case kvstore.WatchOpDelete: - actionName = "delete" + action = registry.Delete default: _ = w.stop() //nolint:errcheck return nil, orberrors.ErrBadRequest.Wrap(errors.New("invalid operation")) } return ®istry.Result{ - Service: &svc, - Action: actionName, + Node: svc, + Action: action, }, nil } diff --git a/registry/mdns/COVERPKGS b/registry/mdns/COVERPKGS new file mode 100644 index 00000000..3b812666 --- /dev/null +++ b/registry/mdns/COVERPKGS @@ -0,0 +1,2 @@ +github.com/go-orb/go-orb/registry +github.com/go-orb/plugins/registry/mdns \ No newline at end of file diff --git a/registry/mdns/README.md b/registry/mdns/README.md new file mode 100644 index 00000000..e03b4017 --- /dev/null +++ b/registry/mdns/README.md @@ -0,0 +1,3 @@ +# mdns registry + +This is the mDNS Registry for Orb, it's basicaly a copy & paste from go-micro.dev/v4. diff --git a/registry/mdns/client/client.go b/registry/mdns/client/client.go new file mode 100644 index 00000000..8c99fd57 --- /dev/null +++ b/registry/mdns/client/client.go @@ -0,0 +1,569 @@ +// Package client provides utility functions for the mdns registry. +package client + +import ( + "context" + "errors" + "fmt" + "net" + "strings" + "sync" + "time" + + "github.com/go-orb/go-orb/log" + "github.com/go-orb/plugins/registry/mdns/server" + "github.com/go-orb/plugins/registry/mdns/util" + "github.com/miekg/dns" + "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" +) + +// ServiceEntry is returned after we query for a service. +type ServiceEntry struct { + Name string + Host string + AddrV4 net.IP + AddrV6 net.IP + Port int + Info string + InfoFields []string + TTL int + Type uint16 + + hasTXT bool + sent bool +} + +// complete is used to check if we have all the info we need. +func (s *ServiceEntry) complete() bool { + return (len(s.AddrV4) > 0 || len(s.AddrV6) > 0) && s.Port != 0 && s.hasTXT +} + +// QueryParam is used to customize how a Lookup is performed. +type QueryParam struct { + Service string // Service to lookup + Domain string // Lookup domain, default "local" + Type uint16 // Lookup type, defaults to dns.TypePTR + Context context.Context // Context + Timeout time.Duration // Lookup timeout, default 1 second. Ignored if Context is provided + Interface *net.Interface // Multicast interface to use + Entries chan<- *ServiceEntry // Entries Channel + WantUnicastResponse bool // Unicast response desired, as per 5.4 in RFC +} + +// DefaultParams is used to return a default set of QueryParam's. +func DefaultParams(service string) *QueryParam { + return &QueryParam{ + Service: service, + Domain: "local", + Timeout: time.Second, + Entries: make(chan *ServiceEntry), + WantUnicastResponse: false, // TODO(reddaly): Change this default. + } +} + +// Query looks up a given service, in a domain, waiting at most +// for a timeout before finishing the query. The results are streamed +// to a channel. Sends will not block, so clients should make sure to +// either read or buffer. +func Query(params *QueryParam) error { + // Create a new client + client, err := newClient() + if err != nil { + return err + } + defer client.Close() //nolint:errcheck + + // Set the multicast interface + if params.Interface != nil { + if err = client.setInterface(params.Interface, false); err != nil { + return err + } + } + + // Ensure defaults are set + if params.Domain == "" { + params.Domain = "local" + } + + if params.Context == nil { + if params.Timeout == 0 { + params.Timeout = time.Second + } + + var cancel context.CancelFunc + + params.Context, cancel = context.WithTimeout(context.Background(), params.Timeout) + defer cancel() + + if err != nil { + return err + } + } + + // Run the query + return client.query(params) +} + +// Listen listens indefinitely for multicast updates. +func Listen(ctx context.Context, entries chan<- *ServiceEntry) error { + // Create a new client + client, err := newClient() + if err != nil { + return err + } + defer client.Close() //nolint:errcheck + + // client.setInterface(nil, true) + + // Start listening for response packets + msgCh := make(chan *dns.Msg, 32) + + go client.recv(client.ipv4UnicastConn, msgCh) + go client.recv(client.ipv6UnicastConn, msgCh) + go client.recv(client.ipv4MulticastConn, msgCh) + go client.recv(client.ipv6MulticastConn, msgCh) + + ip := make(map[string]*ServiceEntry) + + for { + select { + case <-ctx.Done(): + return nil + case <-client.closedCh: + return nil + case m := <-msgCh: + e := messageToEntry(m, ip) + if e == nil { + continue + } + + // Check if this entry is complete + if e.complete() { + if e.sent { + continue + } + + e.sent = true + entries <- e + + ip = make(map[string]*ServiceEntry) + } else { + // Fire off a node specific query + m := new(dns.Msg) + m.SetQuestion(e.Name, dns.TypePTR) + m.RecursionDesired = false + + if err := client.sendQuery(m); err != nil { + log.Error("[mdns] failed to query instance %s: %v", err, e.Name) + } + } + } + } +} + +// Lookup is the same as Query, however it uses all the default parameters. +func Lookup(service string, entries chan<- *ServiceEntry) error { + params := DefaultParams(service) + params.Entries = entries + + return Query(params) +} + +// Client provides a query interface that can be used to +// search for service providers using mDNS. +type client struct { + ipv4UnicastConn *net.UDPConn + ipv6UnicastConn *net.UDPConn + + ipv4MulticastConn *net.UDPConn + ipv6MulticastConn *net.UDPConn + + closed bool + closedCh chan struct{} // TODO(reddaly): This doesn't appear to be used. + closeLock sync.Mutex +} + +// NewClient creates a new mdns Client that can be used to query +// for records. +func newClient() (*client, error) { //nolint:funlen,gocyclo + // TODO(reddaly): At least attempt to bind to the port required in the spec. + // Create a IPv4 listener + uconn4, err4 := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0}) + uconn6, err6 := net.ListenUDP("udp6", &net.UDPAddr{IP: net.IPv6zero, Port: 0}) + + if err4 != nil && err6 != nil { + log.Error("[mdns] failed to bind to udp port: %v %v", err4, err6) + } + + if uconn4 == nil && uconn6 == nil { + return nil, errors.New("failed to bind to any unicast udp port") + } + + if uconn4 == nil { + uconn4 = &net.UDPConn{} + } + + if uconn6 == nil { + uconn6 = &net.UDPConn{} + } + + mconn4, err4 := net.ListenUDP("udp4", server.MDNSWildcardAddrIPv4) + mconn6, err6 := net.ListenUDP("udp6", server.MDNSWildcardAddrIPv6) + + if err4 != nil && err6 != nil { + log.Error("[mdns] failed to bind to udp port: %v %v", err4, err6) + } + + if mconn4 == nil && mconn6 == nil { + return nil, errors.New("failed to bind to any multicast udp port") + } + + if mconn4 == nil { + mconn4 = &net.UDPConn{} + } + + if mconn6 == nil { + mconn6 = &net.UDPConn{} + } + + p1 := ipv4.NewPacketConn(mconn4) + p2 := ipv6.NewPacketConn(mconn6) + + if err := p1.SetMulticastLoopback(true); err != nil { + return nil, err + } + + if err := p2.SetMulticastLoopback(true); err != nil { + return nil, err + } + + ifaces, err := net.Interfaces() + if err != nil { + return nil, err + } + + // Check if we manage to succeed on atleast one interface. + success := false + + for _, iface := range ifaces { + i := iface + if err := p1.JoinGroup(&i, &net.UDPAddr{IP: server.MDNSGroupIPv4}); err != nil { + continue + } + + i = iface + if err := p2.JoinGroup(&i, &net.UDPAddr{IP: server.MDNSGroupIPv6}); err != nil { + continue + } + + success = true + } + + if !success { + return nil, errors.New("failed to join multicast group on all interfaces") + } + + c := &client{ + ipv4MulticastConn: mconn4, + ipv6MulticastConn: mconn6, + ipv4UnicastConn: uconn4, + ipv6UnicastConn: uconn6, + closedCh: make(chan struct{}), + } + + return c, nil +} + +// Close is used to cleanup the client. +func (c *client) Close() error { + c.closeLock.Lock() + defer c.closeLock.Unlock() + + if c.closed { + return nil + } + + c.closed = true + + close(c.closedCh) + + var gerr error + + if c.ipv4UnicastConn != nil { + if err := c.ipv4UnicastConn.Close(); err != nil { + gerr = fmt.Errorf("close ipv4 unicast connection: %w", err) + } + } + + if c.ipv6UnicastConn != nil { + if err := c.ipv6UnicastConn.Close(); err != nil { + gerr = fmt.Errorf("close ipv6 unicast connection: %w", err) + } + } + + if c.ipv4MulticastConn != nil { + if err := c.ipv4MulticastConn.Close(); err != nil { + gerr = fmt.Errorf("close ipv4 multicast connection: %w", err) + } + } + + if c.ipv6MulticastConn != nil { + if err := c.ipv6MulticastConn.Close(); err != nil { + gerr = fmt.Errorf("close ipv6 multicast connection: %w", err) + } + } + + return gerr +} + +// setInterface is used to set the query interface, uses system +// default if not provided. +func (c *client) setInterface(iface *net.Interface, loopback bool) error { + p := ipv4.NewPacketConn(c.ipv4UnicastConn) + if err := p.JoinGroup(iface, &net.UDPAddr{IP: server.MDNSGroupIPv4}); err != nil { + return err + } + + p2 := ipv6.NewPacketConn(c.ipv6UnicastConn) + if err := p2.JoinGroup(iface, &net.UDPAddr{IP: server.MDNSGroupIPv6}); err != nil { + return err + } + + p = ipv4.NewPacketConn(c.ipv4MulticastConn) + if err := p.JoinGroup(iface, &net.UDPAddr{IP: server.MDNSGroupIPv4}); err != nil { + return err + } + + p2 = ipv6.NewPacketConn(c.ipv6MulticastConn) + if err := p2.JoinGroup(iface, &net.UDPAddr{IP: server.MDNSGroupIPv6}); err != nil { + return err + } + + if loopback { + if err := p.SetMulticastLoopback(true); err != nil { + return err + } + + if err := p2.SetMulticastLoopback(true); err != nil { + return err + } + } + + return nil +} + +// query is used to perform a lookup and stream results. +func (c *client) query(params *QueryParam) error { + // Create the service name + serviceAddr := fmt.Sprintf("%s.%s.", util.TrimDot(params.Service), util.TrimDot(params.Domain)) + + // Start listening for response packets + msgCh := make(chan *dns.Msg, 32) + go c.recv(c.ipv4UnicastConn, msgCh) + go c.recv(c.ipv6UnicastConn, msgCh) + go c.recv(c.ipv4MulticastConn, msgCh) + go c.recv(c.ipv6MulticastConn, msgCh) + + // Send the query + msg := new(dns.Msg) + if params.Type == dns.TypeNone { + msg.SetQuestion(serviceAddr, dns.TypePTR) + } else { + msg.SetQuestion(serviceAddr, params.Type) + } + // RFC 6762, section 18.12. Repurposing of Top Bit of qclass in Question + // Section + // + // In the Question Section of a Multicast DNS query, the top bit of the qclass + // field is used to indicate that unicast responses are preferred for this + // particular question. (See Section 5.4.) + if params.WantUnicastResponse { + msg.Question[0].Qclass |= 1 << 15 + } + + msg.RecursionDesired = false + + if err := c.sendQuery(msg); err != nil { + return err + } + + // Map the in-progress responses + inprogress := make(map[string]*ServiceEntry) + + for { + select { + case resp := <-msgCh: + inp := messageToEntry(resp, inprogress) + + if inp == nil { + continue + } + + if len(resp.Question) == 0 || resp.Question[0].Name != msg.Question[0].Name { + // discard anything which we've not asked for + continue + } + + // Check if this entry is complete + if inp.complete() { + if inp.sent { + continue + } + + inp.sent = true + select { + case params.Entries <- inp: + case <-params.Context.Done(): + return nil + } + } else { + // Fire off a node specific query + m := new(dns.Msg) + m.SetQuestion(inp.Name, inp.Type) + m.RecursionDesired = false + + if err := c.sendQuery(m); err != nil { + log.Error("[mdns] failed to query instance %s", err, inp.Name) + } + } + case <-params.Context.Done(): + return nil + } + } +} + +// sendQuery is used to multicast a query out. +func (c *client) sendQuery(q *dns.Msg) error { + buf, err := q.Pack() + if err != nil { + return err + } + + if c.ipv4UnicastConn != nil { + if _, err := c.ipv4UnicastConn.WriteToUDP(buf, server.IPv4Addr); err != nil { + return err + } + } + + if c.ipv6UnicastConn != nil { + if _, err := c.ipv6UnicastConn.WriteToUDP(buf, server.IPv6Addr); err != nil { + return err + } + } + + return nil +} + +// recv is used to receive until we get a shutdown. +func (c *client) recv(l *net.UDPConn, msgCh chan *dns.Msg) { + if l == nil { + return + } + + buf := make([]byte, 65536) + + for { + c.closeLock.Lock() + if c.closed { + c.closeLock.Unlock() + return + } + + c.closeLock.Unlock() + + n, err := l.Read(buf) + if err != nil { + continue + } + + msg := new(dns.Msg) + if err := msg.Unpack(buf[:n]); err != nil { + continue + } + select { + case msgCh <- msg: + case <-c.closedCh: + return + } + } +} + +// entryFromMap is used to get or create a entry from/into the map inprogress. +func entryFromMap(inprogress map[string]*ServiceEntry, name string, typ uint16) *ServiceEntry { + if inp, ok := inprogress[name]; ok { + return inp + } + + inp := &ServiceEntry{ + Name: name, + Type: typ, + } + + inprogress[name] = inp + + return inp +} + +func messageToEntry(m *dns.Msg, inprogress map[string]*ServiceEntry) *ServiceEntry { + var inp *ServiceEntry + + for _, answer := range append(m.Answer, m.Extra...) { + // TODO(reddaly): Check that response corresponds to serviceAddr? + switch dnsAnswer := answer.(type) { + case *dns.PTR: + // Create new entry for this + inp = entryFromMap(inprogress, dnsAnswer.Ptr, dnsAnswer.Hdr.Rrtype) + if inp.complete() { + continue + } + case *dns.SRV: + // Check for a target mismatch + if dnsAnswer.Target != dnsAnswer.Hdr.Name { + srcEntry := entryFromMap(inprogress, dnsAnswer.Hdr.Name, dnsAnswer.Hdr.Rrtype) + inprogress[dnsAnswer.Target] = srcEntry + } + + // Get the port + inp = entryFromMap(inprogress, dnsAnswer.Hdr.Name, dnsAnswer.Hdr.Rrtype) + if inp.complete() { + continue + } + + inp.Host = dnsAnswer.Target + inp.Port = int(dnsAnswer.Port) + case *dns.TXT: + // Pull out the txt + inp = entryFromMap(inprogress, dnsAnswer.Hdr.Name, dnsAnswer.Hdr.Rrtype) + if inp.complete() { + continue + } + + inp.Info = strings.Join(dnsAnswer.Txt, "|") + inp.InfoFields = dnsAnswer.Txt + inp.hasTXT = true + case *dns.A: + // Pull out the IP + inp = entryFromMap(inprogress, dnsAnswer.Hdr.Name, dnsAnswer.Hdr.Rrtype) + if inp.complete() { + continue + } + + inp.AddrV4 = dnsAnswer.A + case *dns.AAAA: + // Pull out the IP + inp = entryFromMap(inprogress, dnsAnswer.Hdr.Name, dnsAnswer.Hdr.Rrtype) + if inp.complete() { + continue + } + + inp.AddrV6 = dnsAnswer.AAAA + } + + if inp != nil { + inp.TTL = int(answer.Header().Ttl) + } + } + + return inp +} diff --git a/registry/mdns/client/client_test.go b/registry/mdns/client/client_test.go new file mode 100644 index 00000000..43cf6bb8 --- /dev/null +++ b/registry/mdns/client/client_test.go @@ -0,0 +1,111 @@ +package client + +import ( + "errors" + "fmt" + "net" + "testing" + "time" + + // "github.com/go-orb/plugins/registry/mdns/client" + "github.com/go-orb/plugins/registry/mdns/server" + "github.com/go-orb/plugins/registry/mdns/zone" +) + +func makeService(t *testing.T) *zone.MDNSService { + t.Helper() + return makeServiceWithServiceName(t, "_http._tcp") +} + +func makeServiceWithServiceName(t *testing.T, service string) *zone.MDNSService { + t.Helper() + + m, err := zone.NewMDNSService( + "hostname", + service, + "local.", + "testhost.", + 80, // port + []net.IP{net.IP([]byte{192, 168, 0, 42}), net.ParseIP("2620:0:1000:1900:b0c2:d0b2:c411:18bc")}, + []string{"Local web server"}, + ) // TXT + if err != nil { + t.Fatalf("err: %v", err) + } + + return m +} + +func TestServer_StartStop(t *testing.T) { + s := makeService(t) + serv, err := server.NewServer(&server.Config{Zone: s, LocalhostChecking: true}) + if err != nil { + t.Fatalf("err: %v", err) + } + defer func() { + if err := serv.Shutdown(); err != nil { + t.Error(err) + } + }() +} + +func TestServer_Lookup(t *testing.T) { + serv, err := server.NewServer( + &server.Config{ + Zone: makeServiceWithServiceName(t, "_foobar._tcp"), + LocalhostChecking: true, + }) + if err != nil { + t.Fatalf("err: %v", err) + } + defer func() { + if err = serv.Shutdown(); err != nil { + t.Error(err) + } + }() + + entries := make(chan *ServiceEntry, 1) + found := false + doneCh := make(chan struct{}) + errChan := make(chan error) + + go func() { + select { + case e := <-entries: + if e.Name != "hostname._foobar._tcp.local." { + errChan <- fmt.Errorf("bad: %v", e) + } + if e.Port != 80 { + errChan <- fmt.Errorf("bad: %v", e) + } + if e.Info != "Local web server" { + errChan <- fmt.Errorf("bad: %v", e) + } + found = true + + case <-time.After(80 * time.Millisecond): + errChan <- errors.New("timeout") + } + close(doneCh) + }() + + params := &QueryParam{ + Service: "_foobar._tcp", + Domain: "local", + Timeout: 50 * time.Millisecond, + Entries: entries, + } + err = Query(params) + if err != nil { + t.Fatalf("err: %v", err) + } + select { + case err := <-errChan: + t.Fatalf("test failed: %v", err) + case <-doneCh: + <-doneCh + } + if !found { + t.Fatalf("record not found") + } +} diff --git a/registry/mdns/config.go b/registry/mdns/config.go new file mode 100644 index 00000000..a4e38af5 --- /dev/null +++ b/registry/mdns/config.go @@ -0,0 +1,54 @@ +package mdns + +import ( + "github.com/go-orb/go-orb/registry" +) + +// Name provides the name of this registry. +const Name = "mdns" + +// Defaults. +// +//nolint:gochecknoglobals +var ( + DefaultDomain = "micro" +) + +func init() { + registry.Plugins.Add(Name, Provide) +} + +// Config provides configuration for the mDNS registry. +type Config struct { + registry.Config `yaml:",inline"` + + Domain string `json:"domain,omitempty" yaml:"domain,omitempty"` +} + +// NewConfig creates a new config object. +func NewConfig( + opts ...registry.Option, +) Config { + cfg := Config{ + Config: registry.NewConfig(), + } + + cfg.Config.Timeout = 500 + + // Apply options. + for _, o := range opts { + o(&cfg) + } + + return cfg +} + +// WithDomain sets the mDNS domain. +func WithDomain(domain string) registry.Option { + return func(c registry.ConfigType) { + cfg, ok := c.(*Config) + if ok { + cfg.Domain = domain + } + } +} diff --git a/registry/mdns/dns/dns_sd.go b/registry/mdns/dns/dns_sd.go new file mode 100644 index 00000000..c8dcbcba --- /dev/null +++ b/registry/mdns/dns/dns_sd.go @@ -0,0 +1,90 @@ +// Package dns provides mdns dns utilities. +package dns + +import ( + "github.com/go-orb/plugins/registry/mdns/zone" + "github.com/miekg/dns" +) + +// SDService is a service that complies with the DNS-SD (RFC 6762) and MDNS +// (RFC 6762) specs for local, multicast-DNS-based discovery. +// +// SDService implements the Zone interface and wraps an MDNSService instance. +// To deploy an mDNS service that is compliant with DNS-SD, it's recommended to +// register only the wrapped instance with the server. +// +// Example usage: +// +// service := &mdns.SDService{ +// MDNSService: &mdns.MDNSService{ +// Instance: "My Foobar Service", +// Service: "_foobar._tcp", +// Port: 8000, +// } +// } +// server, err := mdns.NewServer(&mdns.Config{Zone: service}) +// if err != nil { +// log.Fatalf("Error creating server: %v", err) +// } +// defer server.Shutdown() +type SDService struct { + MDNSService *zone.MDNSService +} + +// Records returns DNS records in response to a DNS question. +// +// This function returns the DNS response of the underlying MDNSService +// instance. It also returns a PTR record for a request for " +// _services._dns-sd._udp.", as described in section 9 of RFC 6763 +// ("Service Type Enumeration"), to allow browsing of the underlying MDNSService +// instance. +func (s *SDService) Records(q dns.Question) []dns.RR { + var recs []dns.RR + if q.Name == "_services._dns-sd._udp."+s.MDNSService.Domain+"." { + recs = s.dnssdMetaQueryRecords(q) + } + + return append(recs, s.MDNSService.Records(q)...) +} + +// dnssdMetaQueryRecords returns the DNS records in response to a "meta-query" +// issued to browse for DNS-SD services, as per section 9. of RFC6763. +// +// A meta-query has a name of the form "_services._dns-sd._udp." where +// Domain is a fully-qualified domain, such as "local.". +func (s *SDService) dnssdMetaQueryRecords(q dns.Question) []dns.RR { + // Intended behavior, as described in the RFC: + // ...it may be useful for network administrators to find the list of + // advertised service types on the network, even if those Service Names + // are just opaque identifiers and not particularly informative in + // isolation. + // + // For this purpose, a special meta-query is defined. A DNS query for PTR + // records with the name "_services._dns-sd._udp." yields a set of + // PTR records, where the rdata of each PTR record is the two-abel + // name, plus the same domain, e.g., "_http._tcp.". + // Including the domain in the PTR rdata allows for slightly better name + // compression in Unicast DNS responses, but only the first two labels are + // relevant for the purposes of service type enumeration. These two-label + // service types can then be used to construct subsequent Service Instance + // Enumeration PTR queries, in this or others, to discover + // instances of that service type. + return []dns.RR{ + &dns.PTR{ + Hdr: dns.RR_Header{ + Name: q.Name, + Rrtype: dns.TypePTR, + Class: dns.ClassINET, + Ttl: zone.DefaultTTL, + }, + Ptr: s.MDNSService.GetServiceAddr(), + }, + } +} + +// Announcement returns DNS records that should be broadcast during the initial +// availability of the service, as described in section 8.3 of RFC 6762. +// TODO(reddaly): Add this when Announcement is added to the mdns.Zone interface. +// func (s *DNSSDService) Announcement() []dns.RR { +// return s.MDNSService.Announcement() +//} diff --git a/registry/mdns/dns/dns_sd_test.go b/registry/mdns/dns/dns_sd_test.go new file mode 100644 index 00000000..9a2329d0 --- /dev/null +++ b/registry/mdns/dns/dns_sd_test.go @@ -0,0 +1,67 @@ +package dns + +import ( + "reflect" + "testing" + + "github.com/go-orb/plugins/registry/mdns/zone" + "github.com/miekg/dns" +) + +// type mockMDNSService struct{} + +// func (s *mockMDNSService) Records(q dns.Question) []dns.RR { +// return []dns.RR{ +// &dns.PTR{ +// Hdr: dns.RR_Header{ +// Name: "fakerecord", +// Rrtype: dns.TypePTR, +// Class: dns.ClassINET, +// Ttl: 42, +// }, +// Ptr: "fake.local.", +// }, +// } +// } + +// func (s *mockMDNSService) Announcement() []dns.RR { +// return []dns.RR{ +// &dns.PTR{ +// Hdr: dns.RR_Header{ +// Name: "fakeannounce", +// Rrtype: dns.TypePTR, +// Class: dns.ClassINET, +// Ttl: 42, +// }, +// Ptr: "fake.local.", +// }, +// } +// } + +func TestDNSSDServiceRecords(t *testing.T) { + s := &SDService{ + MDNSService: &zone.TestMDNSService, + } + q := dns.Question{ + Name: "_services._dns-sd._udp.local.", + Qtype: dns.TypePTR, + Qclass: dns.ClassINET, + } + recs := s.Records(q) + if got, want := len(recs), 1; got != want { + t.Fatalf("s.Records(%v) returned %v records, want %v", q, got, want) + } + + want := dns.RR(&dns.PTR{ + Hdr: dns.RR_Header{ + Name: "_services._dns-sd._udp.local.", + Rrtype: dns.TypePTR, + Class: dns.ClassINET, + Ttl: zone.DefaultTTL, + }, + Ptr: "_foobar._tcp.local.", + }) + if got := recs[0]; !reflect.DeepEqual(got, want) { + t.Errorf("s.Records()[0] = %v, want %v", got, want) + } +} diff --git a/registry/mdns/go.mod b/registry/mdns/go.mod new file mode 100644 index 00000000..259c118d --- /dev/null +++ b/registry/mdns/go.mod @@ -0,0 +1,29 @@ +module github.com/go-orb/plugins/registry/mdns + +go 1.23.6 + +require ( + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122813-09813c7b9d65 + github.com/lithammer/shortuuid/v3 v3.0.7 + github.com/miekg/dns v1.1.63 + github.com/stretchr/testify v1.10.0 + golang.org/x/net v0.37.0 +) + +require ( + dario.cat/mergo v1.0.1 // indirect + github.com/cornelk/hashmap v1.0.8 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + golang.org/x/mod v0.24.0 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/tools v0.31.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/registry/mdns/go.sum b/registry/mdns/go.sum new file mode 100644 index 00000000..b5a28e37 --- /dev/null +++ b/registry/mdns/go.sum @@ -0,0 +1,51 @@ +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= +github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +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/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 h1:Fj2tX19g5TxjS9pHyDV4ZMLkZYW4cuNJ6yh149HRJ84= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:U4rbrSlCGhQaiJxl4GRwIQLUv+Cg8og9NEEInd9j8ww= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 h1:6pxnS4Kg1WRSMKU2DFVl40EFlO06YT7gT/d0uK8ZEB4= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:VLPoWEGe+/gcCUZnp3/WJXBP35C22+14CmjrIZegfQY= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122813-09813c7b9d65 h1:InnSP/542m8MeczOjL14qtnpeGu14od2PAtedfRPrg8= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:qUq39uHPQ6qZZxNFtH3IPb01vWESqwSJrzUvrzAiBzc= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8= +github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts= +github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= +github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= +golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/registry/mdns/mdns.go b/registry/mdns/mdns.go new file mode 100644 index 00000000..86937253 --- /dev/null +++ b/registry/mdns/mdns.go @@ -0,0 +1,556 @@ +// Package mdns provides a multicast dns registry +package mdns + +import ( + "bytes" + "compress/zlib" + "context" + "encoding/hex" + "errors" + "fmt" + "io" + "net" + "slices" + "strconv" + "strings" + "sync" + + "log/slog" + + "github.com/go-orb/plugins/registry/mdns/client" + "github.com/go-orb/plugins/registry/mdns/dns" + "github.com/go-orb/plugins/registry/mdns/server" + "github.com/go-orb/plugins/registry/mdns/zone" + "github.com/go-orb/plugins/registry/regutil/cache" + + "github.com/go-orb/go-orb/codecs" + "github.com/go-orb/go-orb/config" + "github.com/go-orb/go-orb/log" + "github.com/go-orb/go-orb/registry" + "github.com/go-orb/go-orb/types" + "github.com/lithammer/shortuuid/v3" +) + +const metaPrefix = "orb_app_" +const myMetaPrefix = "orb_internal_" +const nodeIDDelimiter = "@" +const nodeKeyDelimiter = "_" + +func nodeID(s registry.ServiceNode) string { + return strings.Join([]string{ + s.Namespace, + s.Region, + s.Name, + s.Version, + s.Scheme, + s.Address, + }, nodeIDDelimiter) +} + +func nodeKey(s registry.ServiceNode) string { + return strings.Join([]string{ + s.Scheme, + s.Version, + }, nodeKeyDelimiter) +} + +func serviceKey(namespace, region, name string) string { + return strings.Join([]string{ + name, + region, + namespace, + }, nodeKeyDelimiter) +} + +func idToNode(id string) (registry.ServiceNode, error) { + parts := strings.Split(id, nodeIDDelimiter) + if len(parts) != 6 { + return registry.ServiceNode{}, errors.New("invalid id format") + } + + return registry.ServiceNode{ + Namespace: parts[0], + Region: parts[1], + Name: parts[2], + Version: parts[3], + Scheme: parts[4], + Address: parts[5], + Metadata: make(map[string]string), + }, nil +} + +type mdnsTxt struct { + ID string `json:"id"` + Metadata map[string]string `json:"metadata"` +} + +type mdnsEntry struct { + id string + node *server.Server +} + +// This is here to make sure RegistryMDNS implements registry.Registry. +var _ registry.Registry = (*Registry)(nil) + +// Registry implements the registry interface. It runs a MDNS service registry. +type Registry struct { + config Config + logger log.Logger + codec codecs.Marshaler + + sync.Mutex + services map[string][]*mdnsEntry + + mtx sync.RWMutex + + // watchers + watchers map[string]*mdnsWatcher + + // watchListener + watchListener chan *client.ServiceEntry + + // cache is used to cache registry operations. + cache *cache.Cache +} + +type mdnsWatcher struct { + ctx context.Context + id string + wo registry.WatchOptions + ch chan *client.ServiceEntry + // the mdns domain + domain string + + logger log.Logger + codec codecs.Marshaler +} + +// Provide creates a new MDNS registry. +func Provide( + datas map[string]any, + _ *types.Components, + logger log.Logger, + opts ...registry.Option, +) (registry.Type, error) { + cfg := NewConfig(opts...) + if err := config.Parse(nil, registry.DefaultConfigSection, datas, &cfg); err != nil && !errors.Is(err, config.ErrNoSuchKey) { + return registry.Type{}, fmt.Errorf("parse config: %w", err) + } + + // Return the new registry. + reg, err := New(cfg, logger) + if err != nil { + return registry.Type{}, fmt.Errorf("create registry: %w", err) + } + + return registry.Type{Registry: reg}, nil +} + +// New creates a new mdns registry. This functions should rarely be called manually. +// To create a new registry use ProvideRegistryMDNS. +func New(cfg Config, log log.Logger) (*Registry, error) { + if cfg.Timeout == 0 { + cfg.Timeout = registry.DefaultTimeout + } + + if cfg.Domain == "" { + cfg.Domain = DefaultDomain + } + + codec, err := codecs.GetMime(codecs.MimeJSON) + if err != nil { + return nil, fmt.Errorf("get codec: %w", err) + } + + reg := &Registry{ + config: cfg, + codec: codec, + logger: log, + services: make(map[string][]*mdnsEntry), + watchers: make(map[string]*mdnsWatcher), + } + + // Initialize the cache with a reference to this registry + reg.cache = cache.New(cache.Config{}, log, reg) + + return reg, nil +} + +// Start the registry. +func (m *Registry) Start(ctx context.Context) error { + return m.cache.Start(ctx) +} + +// Stop the registry. +func (m *Registry) Stop(ctx context.Context) error { + return m.cache.Stop(ctx) +} + +// String returns the plugin name. +func (m *Registry) String() string { + return Name +} + +// Type returns the component type. +func (m *Registry) Type() string { + return registry.ComponentType +} + +// Register registes a service's nodes to the registry. +func (m *Registry) Register(_ context.Context, node registry.ServiceNode) error { + m.Lock() + entries, ok := m.services[serviceKey(node.Namespace, node.Region, node.Name)] + m.Unlock() + + // first entry, create wildcard used for list queries + if !ok { + s, err := zone.NewMDNSService( + serviceKey(node.Namespace, node.Region, node.Name), + "_services", + m.config.Domain+".", + "", + 9999, + []net.IP{net.ParseIP("0.0.0.0")}, + nil, + ) + if err != nil { + return err + } + + srv, err := server.NewServer(&server.Config{Zone: &dns.SDService{MDNSService: s}}) + if err != nil { + return err + } + + // append the wildcard entry + entries = append(entries, &mdnsEntry{id: "*", node: srv}) + } + + entries, err := m.registerNodes(node, entries) + + // Save + m.Lock() + m.services[serviceKey(node.Namespace, node.Region, node.Name)] = entries + m.Unlock() + + return err +} + +func (m *Registry) registerNodes(node registry.ServiceNode, entries []*mdnsEntry) ([]*mdnsEntry, error) { + id := nodeID(node) + + entry := &mdnsEntry{} + + // Add service metadata to the service + metadata := make(map[string]string) + for k, v := range node.Metadata { + metadata[metaPrefix+k] = v + } + + txt, err := encode(m.codec, &mdnsTxt{ + ID: id, + Metadata: metadata, + }) + + if err != nil { + return entries, err + } + + host, pt, err := net.SplitHostPort(node.Address) + if err != nil { + return entries, err + } + + port, _ := strconv.Atoi(pt) //nolint:errcheck + + // we got here, new node + s, err := zone.NewMDNSService( + nodeKey(node), + serviceKey(node.Namespace, node.Region, node.Name), + m.config.Domain+".", + "", + port, + []net.IP{net.ParseIP(host)}, + txt, + ) + if err != nil { + return entries, err + } + + srv, err := server.NewServer(&server.Config{Zone: s, LocalhostChecking: true}) + if err != nil { + return entries, err + } + + entry.id = id + entry.node = srv + + // Check if the entry already exists + idx := slices.IndexFunc(entries, func(e *mdnsEntry) bool { + return e.id == id + }) + + if idx == -1 { + entries = append(entries, entry) + + m.logger.Trace("created a new node", + slog.String("id", id), + ) + } else { + entries[idx] = entry + + m.logger.Trace("updated existing node", + slog.String("id", id), + ) + } + + return entries, nil +} + +// Deregister a service from the registry. +func (m *Registry) Deregister(_ context.Context, node registry.ServiceNode) error { + m.Lock() + defer m.Unlock() + + // Create a unique node ID similar to registration + nodeID := nodeID(node) + + var keepEntries []*mdnsEntry + + // loop existing entries, check if any match, shutdown those that do + for _, entry := range m.services[serviceKey(node.Namespace, node.Region, node.Name)] { + var remove bool + + if entry.id == nodeID { + m.logger.Trace("deregistering node", "id", nodeID) + + if err := entry.node.Shutdown(); err != nil { + m.logger.Error("Failed to shutdown node", "err", err) + } + + remove = true + } + + // keep it? + if !remove { + keepEntries = append(keepEntries, entry) + } + } + + // last entry is the wildcard for list queries. Remove it. + if len(keepEntries) == 1 && keepEntries[0].id == "*" { + m.logger.Trace("unlisting service", "service", node.Name) + + if err := keepEntries[0].node.Shutdown(); err != nil { + m.logger.Error("failed to shutdown node", "err", err) + } + + delete(m.services, node.Name) + } else { + m.services[node.Name] = keepEntries + } + + return nil +} + +// GetService fetches a service from the registry. +func (m *Registry) GetService(ctx context.Context, namespace, region, name string, schemes []string) ([]registry.ServiceNode, error) { + return m.cache.GetService(ctx, namespace, region, name, schemes) +} + +// ListServices fetches all services in the registry. +func (m *Registry) ListServices(ctx context.Context, namespace, region string, schemes []string) ([]registry.ServiceNode, error) { + return m.cache.ListServices(ctx, namespace, region, schemes) +} + +// Watch for registration changes. +func (m *Registry) Watch(ctx context.Context, opts ...registry.WatchOption) (registry.Watcher, error) { + var wo registry.WatchOptions + for _, o := range opts { + o(&wo) + } + + watcher := &mdnsWatcher{ + ctx: ctx, + id: shortuuid.New(), + wo: wo, + ch: make(chan *client.ServiceEntry, 32), + domain: m.config.Domain, + logger: m.logger.With("watcher", "mdns"), + codec: m.codec, + } + + m.mtx.Lock() + + // Save the watcher + m.watchers[watcher.id] = watcher + + // Check existing listener + if m.watchListener != nil { + m.mtx.Unlock() + + m.logger.Debug("Listener already exists, skipping") + + return watcher, nil + } + + // Reset the listener + m.watchListener = make(chan *client.ServiceEntry, 32) + + m.mtx.Unlock() + + // Send messages to the watchers + go func() { + for { + select { + case <-ctx.Done(): + return + case e, ok := <-m.watchListener: + if !ok { + continue + } + + // Send service entry to all watchers + m.mtx.RLock() + for _, w := range m.watchers { + select { + case w.ch <- e: + default: + } + } + m.mtx.RUnlock() + } + } + }() + + go func() { + // Start listening, blocking call + if err := client.Listen(ctx, m.watchListener); err != nil { + m.logger.Error("Failed to listen", "err", err) + } + + // mdns.Listen has unblocked + // Kill the saved listener + m.mtx.Lock() + + close(m.watchListener) + + m.mtx.Unlock() + }() + + return watcher, nil +} + +func (w *mdnsWatcher) Next() (*registry.Result, error) { + select { + case <-w.ctx.Done(): + return nil, registry.ErrWatcherStopped + case entry := <-w.ch: + txt, err := decode(w.codec, entry.InfoFields) + if err != nil { + w.logger.Debug("Failed to decode entry", "err", err) + return nil, err + } + + // Create a service node from the entry + serviceNode, err := idToNode(txt.ID) + if err != nil { + w.logger.Debug("Failed to create service node", "err", err) + return nil, err + } + + for k, v := range txt.Metadata { + if strings.HasPrefix(k, myMetaPrefix) { + continue + } + + if strings.HasPrefix(k, metaPrefix) { + serviceNode.Metadata[strings.TrimPrefix(k, metaPrefix)] = v + } + } + + // Filter for TTL + if entry.TTL == 0 { + // Delete the service + serviceNode.Metadata["mdns-ttl"] = "expired" + + return ®istry.Result{ + Action: registry.Delete, + Node: serviceNode, + }, nil + } + + // Create the service + return ®istry.Result{ + Action: registry.Create, + Node: serviceNode, + }, nil + } +} + +func encode(codec codecs.Marshaler, txt *mdnsTxt) ([]string, error) { + b, err := codec.Marshal(txt) + if err != nil { + return nil, err + } + + var buf bytes.Buffer + defer buf.Reset() + + w := zlib.NewWriter(&buf) + if _, err := w.Write(b); err != nil { + return nil, err + } + + if err := w.Close(); err != nil { + return nil, err + } + + encoded := hex.EncodeToString(buf.Bytes()) + + // individual txt limit + if len(encoded) <= 255 { + return []string{encoded}, nil + } + + // split encoded string + var record []string + + for len(encoded) > 255 { + record = append(record, encoded[:255]) + encoded = encoded[255:] + } + + record = append(record, encoded) + + return record, nil +} + +func decode(codec codecs.Marshaler, record []string) (*mdnsTxt, error) { + encoded := strings.Join(record, "") + + hr, err := hex.DecodeString(encoded) + if err != nil { + return nil, err + } + + br := bytes.NewReader(hr) + + zr, err := zlib.NewReader(br) + if err != nil { + return nil, err + } + + rbuf, err := io.ReadAll(zr) + if err != nil { + return nil, err + } + + var txt *mdnsTxt + + if err := codec.Unmarshal(rbuf, &txt); err != nil { + return nil, err + } + + return txt, nil +} diff --git a/registry/mdns/mdns_test.go b/registry/mdns/mdns_test.go new file mode 100644 index 00000000..35ab4e04 --- /dev/null +++ b/registry/mdns/mdns_test.go @@ -0,0 +1,94 @@ +package mdns + +import ( + "context" + "testing" + "time" + + "github.com/go-orb/go-orb/log" + "github.com/go-orb/go-orb/registry" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + _ "github.com/go-orb/plugins/codecs/json" + _ "github.com/go-orb/plugins/log/slog" + "github.com/go-orb/plugins/registry/tests" +) + +func createSuite() (*tests.TestSuite, func() error, error) { + ctx := context.Background() + + logger, err := log.New(log.WithLevel(log.LevelTrace)) + if err != nil { + log.Error("failed to create logger", "err", err) + return nil, func() error { return nil }, err + } + + cfg1 := NewConfig(WithDomain("orb.local")) + reg1, err := New(cfg1, logger) + if err != nil { + log.Error("failed to create registry one", "err", err) + return nil, func() error { return nil }, err + } + if err := reg1.Start(ctx); err != nil { + log.Error("failed to connect registry one to Consul server", "err", err) + return nil, func() error { return nil }, err + } + + // cfg2 := NewConfig(WithDomain("orb.local")) + // reg2, err := New(cfg2, logger) + // if err != nil { + // log.Error("failed to create registry two", "err", err) + // return nil, func() error { return nil }, err + // } + // if err := reg2.Start(ctx); err != nil { + // log.Error("failed to connect registry two to Consul server", "err", err) + // return nil, func() error { return nil }, err + // } + + cleanup := func() error { + ctx := context.Background() + _ = reg1.Stop(ctx) //nolint:errcheck + // _ = reg2.Stop(ctx) //nolint:errcheck + return nil + } + + return tests.CreateSuite(logger, []registry.Registry{reg1}, time.Second), cleanup, nil +} + +func TestSuite(t *testing.T) { + s, cleanup, err := createSuite() + require.NoError(t, err, "while creating a server") + + // Run the tests. + suite.Run(t, s) + + require.NoError(t, cleanup(), "while cleaning up") +} + +func BenchmarkGetService(b *testing.B) { + s, cleanup, err := createSuite() + require.NoError(b, err, "while creating a server") + + s.BenchmarkGetService(b) + + require.NoError(b, cleanup(), "while cleaning up") +} + +func BenchmarkParallelGetService(b *testing.B) { + s, cleanup, err := createSuite() + require.NoError(b, err, "while creating a server") + + s.BenchmarkGetService(b) + + require.NoError(b, cleanup(), "while cleaning up") +} + +func BenchmarkGetServiceWithNoNodes(b *testing.B) { + s, cleanup, err := createSuite() + require.NoError(b, err, "while creating a server") + + s.BenchmarkGetServiceWithNoNodes(b) + + require.NoError(b, cleanup(), "while cleaning up") +} diff --git a/registry/mdns/server/server.go b/registry/mdns/server/server.go new file mode 100644 index 00000000..a30c38c1 --- /dev/null +++ b/registry/mdns/server/server.go @@ -0,0 +1,593 @@ +// Package server provides an MDNS server. +package server + +import ( + "errors" + "fmt" + "math/rand" + "net" + "sync" + "sync/atomic" + "time" + + "github.com/go-orb/go-orb/log" + "github.com/miekg/dns" + "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" + + "github.com/go-orb/plugins/registry/mdns/util" + "github.com/go-orb/plugins/registry/mdns/zone" +) + +// mDNS Groups. +// +//nolint:gochecknoglobals +var ( + MDNSGroupIPv4 = net.ParseIP("224.0.0.251") + MDNSGroupIPv6 = net.ParseIP("ff02::fb") +) + +// mDNS wildcard addresses. +// +//nolint:gochecknoglobals +var ( + MDNSWildcardAddrIPv4 = &net.UDPAddr{ + IP: net.ParseIP("224.0.0.0"), + Port: 5353, + } + MDNSWildcardAddrIPv6 = &net.UDPAddr{ + IP: net.ParseIP("ff02::"), + Port: 5353, + } +) + +// mDNS endpoint addresses. +// +//nolint:gochecknoglobals +var ( + IPv4Addr = &net.UDPAddr{ + IP: MDNSGroupIPv4, + Port: 5353, + } + IPv6Addr = &net.UDPAddr{ + IP: MDNSGroupIPv6, + Port: 5353, + } +) + +// GetMachineIP is a func which returns the outbound IP of this machine. +// Used by the server to determine whether to attempt send the response on a local address. +type GetMachineIP func() net.IP + +// Config is used to configure the mDNS server. +type Config struct { + // Zone must be provided to support responding to queries + Zone zone.Zone + + // Iface if provided binds the multicast listener to the given + // interface. If not provided, the system default multicase interface + // is used. + Iface *net.Interface + + // Port If it is not 0, replace the port 5353 with this port number. + Port int + + // GetMachineIP is a function to return the IP of the local machine + GetMachineIP GetMachineIP + + // LocalhostChecking if enabled asks the server to also send responses to + // 0.0.0.0 if the target IP + // is this host (as defined by GetMachineIP). + // Useful in case machine is on a VPN which blocks comms on non standard ports + LocalhostChecking bool +} + +// Server is an mDNS server used to listen for mDNS queries and respond if we +// have a matching local record. +type Server struct { + config *Config + + ipv4List *net.UDPConn + ipv6List *net.UDPConn + + shutdown bool + shutdownCh chan struct{} + shutdownLock sync.Mutex + wg sync.WaitGroup + + outboundIP net.IP +} + +// NewServer is used to create a new mDNS server from a config. +func NewServer(config *Config) (*Server, error) { //nolint:gocyclo,funlen + setCustomPort(config.Port) + + // Create the listeners + // Create wildcard connections (because :5353 can be already taken by other apps) + ipv4List, _ := net.ListenUDP("udp4", MDNSWildcardAddrIPv4) //nolint:errcheck + ipv6List, _ := net.ListenUDP("udp6", MDNSWildcardAddrIPv6) //nolint:errcheck + + if ipv4List == nil && ipv6List == nil { + return nil, errors.New("mdns: failed to bind to any udp port") + } + + if ipv4List == nil { + ipv4List = &net.UDPConn{} + } + + if ipv6List == nil { + ipv6List = &net.UDPConn{} + } + + // Join multicast groups to receive announcements + connIPv4 := ipv4.NewPacketConn(ipv4List) + connIPv6 := ipv6.NewPacketConn(ipv6List) + + if err := connIPv4.SetMulticastLoopback(true); err != nil { + return nil, err + } + + if err := connIPv6.SetMulticastLoopback(true); err != nil { + return nil, err + } + + if config.Iface != nil { //nolint:nestif + if err := connIPv4.JoinGroup(config.Iface, &net.UDPAddr{IP: MDNSGroupIPv4}); err != nil { + return nil, err + } + + if err := connIPv6.JoinGroup(config.Iface, &net.UDPAddr{IP: MDNSGroupIPv6}); err != nil { + return nil, err + } + } else { + ifaces, err := net.Interfaces() + if err != nil { + return nil, err + } + + // Check if we succeed on atleast one interface. + success := false + + for _, iface := range ifaces { + i := iface + if err := connIPv4.JoinGroup(&i, &net.UDPAddr{IP: MDNSGroupIPv4}); err != nil { + continue + } + + i = iface + if err := connIPv6.JoinGroup(&i, &net.UDPAddr{IP: MDNSGroupIPv6}); err != nil { + continue + } + + success = true + } + + if !success { + return nil, errors.New("failed to join multicast group on all interfaces") + } + } + + ipFunc := getOutboundIP + if config.GetMachineIP != nil { + ipFunc = config.GetMachineIP + } + + s := &Server{ + config: config, + ipv4List: ipv4List, + ipv6List: ipv6List, + shutdownCh: make(chan struct{}), + outboundIP: ipFunc(), + } + + go s.recv(s.ipv4List) + go s.recv(s.ipv6List) + + s.wg.Add(1) + + go s.probe() + + return s, nil +} + +// Shutdown is used to shutdown the listener. +func (s *Server) Shutdown() error { + s.shutdownLock.Lock() + defer s.shutdownLock.Unlock() + + if s.shutdown { + return nil + } + + s.shutdown = true + close(s.shutdownCh) + + if err := s.unregister(); err != nil { + return err + } + + s.wg.Wait() + + var gerr error + + if s.ipv4List != nil { + if err := s.ipv4List.Close(); err != nil { + gerr = fmt.Errorf("close IPv4 UDP connection: %w", err) + } + } + + if s.ipv6List != nil { + if err := s.ipv6List.Close(); err != nil { + gerr = fmt.Errorf("close IPv4 UDP connection: %w", err) + } + } + + return gerr +} + +// recv is a long running routine to receive packets from an interface. +func (s *Server) recv(c *net.UDPConn) { + if c == nil { + return + } + + buf := make([]byte, 65536) + + for { + s.shutdownLock.Lock() + if s.shutdown { + s.shutdownLock.Unlock() + return + } + s.shutdownLock.Unlock() + + n, from, err := c.ReadFrom(buf) + if err != nil { + continue + } + + if err := s.parsePacket(buf[:n], from); err != nil { + log.Error("[ERR] mdns: Failed to handle query", err) + } + } +} + +// parsePacket is used to parse an incoming packet. +func (s *Server) parsePacket(packet []byte, from net.Addr) error { + var msg dns.Msg + if err := msg.Unpack(packet); err != nil { + log.Error("[ERR] mdns: Failed to unpack packet", err) + return err + } + // TODO: This is a bit of a hack + // We decided to ignore some mDNS answers for the time being + // See: https://tools.ietf.org/html/rfc6762#section-7.2 + msg.Truncated = false + + return s.handleQuery(&msg, from) +} + +// handleQuery is used to handle an incoming query. +func (s *Server) handleQuery(query *dns.Msg, from net.Addr) error { + if query.Opcode != dns.OpcodeQuery { + // "In both multicast query and multicast response messages, the OPCODE MUST + // be zero on transmission (only standard queries are currently supported + // over multicast). Multicast DNS messages received with an OPCODE other + // than zero MUST be silently ignored." Note: OpcodeQuery == 0 + return fmt.Errorf("mdns: received query with non-zero Opcode %v: %v", query.Opcode, *query) + } + + if query.Rcode != 0 { + // "In both multicast query and multicast response messages, the Response + // Code MUST be zero on transmission. Multicast DNS messages received with + // non-zero Response Codes MUST be silently ignored." + return fmt.Errorf("mdns: received query with non-zero Rcode %v: %v", query.Rcode, *query) + } + + // TODO(reddaly): Handle "TC (Truncated) Bit": + // In query messages, if the TC bit is set, it means that additional + // Known-Answer records may be following shortly. A responder SHOULD + // record this fact, and wait for those additional Known-Answer records, + // before deciding whether to respond. If the TC bit is clear, it means + // that the querying host has no additional Known Answers. + if query.Truncated { + return fmt.Errorf("[ERR] mdns: support for DNS requests with high truncated bit not implemented: %v", *query) + } + + var unicastAnswer, multicastAnswer []dns.RR + + // Handle each question + for _, q := range query.Question { + mrecs, urecs := s.handleQuestion(q) + multicastAnswer = append(multicastAnswer, mrecs...) + unicastAnswer = append(unicastAnswer, urecs...) + } + + // See section 18 of RFC 6762 for rules about DNS headers. + resp := func(unicast bool) *dns.Msg { + // 18.1: ID (Query Identifier) + // 0 for multicast response, query.Id for unicast response + id := uint16(0) + if unicast { + id = query.Id + } + + var answer []dns.RR + if unicast { + answer = unicastAnswer + } else { + answer = multicastAnswer + } + + if len(answer) == 0 { + return nil + } + + return &dns.Msg{ + MsgHdr: dns.MsgHdr{ + Id: id, + + // 18.2: QR (Query/Response) Bit - must be set to 1 in response. + Response: true, + + // 18.3: OPCODE - must be zero in response (OpcodeQuery == 0) + Opcode: dns.OpcodeQuery, + + // 18.4: AA (Authoritative Answer) Bit - must be set to 1 + Authoritative: true, + + // The following fields must all be set to 0: + // 18.5: TC (TRUNCATED) Bit + // 18.6: RD (Recursion Desired) Bit + // 18.7: RA (Recursion Available) Bit + // 18.8: Z (Zero) Bit + // 18.9: AD (Authentic Data) Bit + // 18.10: CD (Checking Disabled) Bit + // 18.11: RCODE (Response Code) + }, + // 18.12 pertains to questions (handled by handleQuestion) + // 18.13 pertains to resource records (handled by handleQuestion) + + // 18.14: Name Compression - responses should be compressed (though see + // caveats in the RFC), so set the Compress bit (part of the dns library + // API, not part of the DNS packet) to true. + Compress: true, + Question: query.Question, + Answer: answer, + } + } + + if mresp := resp(false); mresp != nil { + if err := s.sendResponse(mresp, from); err != nil { + return fmt.Errorf("mdns: error sending multicast response: %w", err) + } + } + + if uresp := resp(true); uresp != nil { + if err := s.sendResponse(uresp, from); err != nil { + return fmt.Errorf("mdns: error sending unicast response: %w", err) + } + } + + return nil +} + +// handleQuestion is used to handle an incoming question +// +// The response to a question may be transmitted over multicast, unicast, or +// both. The return values are DNS records for each transmission type. +func (s *Server) handleQuestion(q dns.Question) (multicastRecs, unicastRecs []dns.RR) { + records := s.config.Zone.Records(q) + if len(records) == 0 { + return nil, nil + } + + // Handle unicast and multicast responses. + // TODO(reddaly): The decision about sending over unicast vs. multicast is not + // yet fully compliant with RFC 6762. For example, the unicast bit should be + // ignored if the records in question are close to TTL expiration. For now, + // we just use the unicast bit to make the decision, as per the spec: + // RFC 6762, section 18.12. Repurposing of Top Bit of qclass in Question + // Section + // + // In the Question Section of a Multicast DNS query, the top bit of the + // qclass field is used to indicate that unicast responses are preferred + // for this particular question. (See Section 5.4.) + if q.Qclass&(1<<15) != 0 { + return nil, records + } + + return records, nil +} + +func (s *Server) probe() { + defer s.wg.Done() + + mdnsService, ok := s.config.Zone.(*zone.MDNSService) + if !ok { + return + } + + name := fmt.Sprintf("%s.%s.%s.", mdnsService.Instance, + util.TrimDot(mdnsService.Service), util.TrimDot(mdnsService.Domain)) + + msg := new(dns.Msg) + msg.SetQuestion(name, dns.TypePTR) + msg.RecursionDesired = false + + srv := &dns.SRV{ + Hdr: dns.RR_Header{ + Name: name, + Rrtype: dns.TypeSRV, + Class: dns.ClassINET, + Ttl: zone.DefaultTTL, + }, + Priority: 0, + Weight: 0, + Port: uint16(mdnsService.Port), //nolint:gosec + Target: mdnsService.HostName, + } + txt := &dns.TXT{ + Hdr: dns.RR_Header{ + Name: name, + Rrtype: dns.TypeTXT, + Class: dns.ClassINET, + Ttl: zone.DefaultTTL, + }, + Txt: mdnsService.TXT, + } + msg.Ns = []dns.RR{srv, txt} + + randomizer := rand.New(rand.NewSource(time.Now().UnixNano())) //nolint:gosec + + for i := 0; i < 3; i++ { + if err := s.SendMulticast(msg); err != nil { + log.Error("[ERR] mdns: failed to send probe", err) + } + + time.Sleep(time.Duration(randomizer.Intn(250)) * time.Millisecond) + } + + resp := new(dns.Msg) + resp.Response = true + + // set for query + msg.SetQuestion(name, dns.TypeANY) + + resp.Answer = append(resp.Answer, s.config.Zone.Records(msg.Question[0])...) + + // reset + msg.SetQuestion(name, dns.TypePTR) + + // From RFC6762 + // The Multicast DNS responder MUST send at least two unsolicited + // responses, one second apart. To provide increased robustness against + // packet loss, a responder MAY send up to eight unsolicited responses, + // provided that the interval between unsolicited responses increases by + // at least a factor of two with every response sent. + timeout := 1 * time.Second + timer := time.NewTimer(timeout) + + for i := 0; i < 3; i++ { + if err := s.SendMulticast(resp); err != nil { + log.Error("[ERR] mdns: failed to send announcement", err) + } + select { + case <-timer.C: + timeout *= 2 + timer.Reset(timeout) + case <-s.shutdownCh: + timer.Stop() + return + } + } +} + +// SendMulticast us used to send a multicast response packet. +func (s *Server) SendMulticast(msg *dns.Msg) error { + buf, err := msg.Pack() + if err != nil { + return err + } + + if s.ipv4List != nil { + if _, err := s.ipv4List.WriteToUDP(buf, IPv4Addr); err != nil { + return err + } + } + + if s.ipv6List != nil { + if _, err := s.ipv6List.WriteToUDP(buf, IPv6Addr); err != nil { + return err + } + } + + return nil +} + +// sendResponse is used to send a response packet. +func (s *Server) sendResponse(resp *dns.Msg, from net.Addr) error { + // TODO(reddaly): Respect the unicast argument, and allow sending responses + // over multicast. + buf, err := resp.Pack() + if err != nil { + return err + } + + // Determine the socket to send from + addr := from.(*net.UDPAddr) //nolint:errcheck + conn := s.ipv4List + backupTarget := net.IPv4zero + + if addr.IP.To4() == nil { + conn = s.ipv6List + backupTarget = net.IPv6zero + } + + _, err = conn.WriteToUDP(buf, addr) + // If the address we're responding to is this machine then we can also + // attempt sending on 0.0.0.0 + // This covers the case where this machine is using a VPN and certain ports + // are blocked so the response never gets there + // Sending two responses is OK + if s.config.LocalhostChecking && addr.IP.Equal(s.outboundIP) { + // ignore any errors, this is best efforts + if _, err = conn.WriteToUDP(buf, &net.UDPAddr{IP: backupTarget, Port: addr.Port}); err != nil { + return err + } + } + + return err +} + +func (s *Server) unregister() error { + sd, ok := s.config.Zone.(*zone.MDNSService) + if !ok { + return nil + } + + atomic.StoreUint32(&sd.TTL, 0) + name := fmt.Sprintf("%s.%s.%s.", sd.Instance, util.TrimDot(sd.Service), util.TrimDot(sd.Domain)) + + q := new(dns.Msg) + q.SetQuestion(name, dns.TypeANY) + + resp := new(dns.Msg) + resp.Response = true + resp.Answer = append(resp.Answer, s.config.Zone.Records(q.Question[0])...) + + return s.SendMulticast(resp) +} + +func setCustomPort(port int) { + if port != 0 { + if MDNSWildcardAddrIPv4.Port != port { + MDNSWildcardAddrIPv4.Port = port + } + + if MDNSWildcardAddrIPv6.Port != port { + MDNSWildcardAddrIPv6.Port = port + } + + if IPv4Addr.Port != port { + IPv4Addr.Port = port + } + + if IPv6Addr.Port != port { + IPv6Addr.Port = port + } + } +} + +func getOutboundIP() net.IP { + conn, err := net.Dial("udp", "8.8.8.8:80") + if err != nil { + // no net connectivity maybe so fallback + return nil + } + defer conn.Close() //nolint:errcheck + + localAddr := conn.LocalAddr().(*net.UDPAddr) //nolint:errcheck + + return localAddr.IP +} diff --git a/registry/mdns/util/util.go b/registry/mdns/util/util.go new file mode 100644 index 00000000..36e9da69 --- /dev/null +++ b/registry/mdns/util/util.go @@ -0,0 +1,9 @@ +// Package util provides utilities. +package util + +import "strings" + +// TrimDot is used to trim the dots from the start or end of a string. +func TrimDot(s string) string { + return strings.Trim(s, ".") +} diff --git a/registry/mdns/zone/zone.go b/registry/mdns/zone/zone.go new file mode 100644 index 00000000..d4dc01e1 --- /dev/null +++ b/registry/mdns/zone/zone.go @@ -0,0 +1,338 @@ +// Package zone provides mDNS zone utilities. +package zone + +import ( + "errors" + "fmt" + "net" + "os" + "sync/atomic" + + "github.com/go-orb/plugins/registry/mdns/util" + "github.com/miekg/dns" +) + +const ( + // DefaultTTL is the default TTL value in returned DNS records in seconds. + DefaultTTL = 120 +) + +// Zone is the interface used to integrate with the server and +// to serve records dynamically. +type Zone interface { + // Records returns DNS records in response to a DNS question. + Records(q dns.Question) []dns.RR +} + +// MDNSService is used to export a named service by implementing a Zone. +type MDNSService struct { + Instance string // Instance name (e.g. "hostService name") + Service string // Service name (e.g. "_http._tcp.") + Domain string // If blank, assumes "local" + HostName string // Host machine DNS name (e.g. "mymachine.net.") + Port int // Service Port + IPs []net.IP // IP addresses for the service's host + TXT []string // Service TXT records + TTL uint32 + serviceAddr string // Fully qualified service address + instanceAddr string // Fully qualified instance address + enumAddr string // _services._dns-sd._udp. +} + +// validateFQDN returns an error if the passed string is not a fully qualified +// hdomain name (more specifically, a hostname). +func validateFQDN(s string) error { + if len(s) == 0 { + return errors.New("FQDN must not be blank") + } + + if s[len(s)-1] != '.' { + return fmt.Errorf("FQDN must end in period: %s", s) + } + // TODO(reddaly): Perform full validation. + + return nil +} + +// NewMDNSService returns a new instance of MDNSService. +// +// If domain, hostName, or ips is set to the zero value, then a default value +// will be inferred from the operating system. +// +// TODO(reddaly): This interface may need to change to account for "unique +// record" conflict rules of the mDNS protocol. Upon startup, the server should +// check to ensure that the instance name does not conflict with other instance +// names, and, if required, select a new name. There may also be conflicting +// hostName A/AAAA records. +func NewMDNSService( + instance, service, domain, hostName string, port int, ips []net.IP, txt []string, +) (*MDNSService, error) { + // Sanity check inputs + if instance == "" { + return nil, errors.New("missing service instance name") + } + + if service == "" { + return nil, errors.New("missing service name") + } + + if port == 0 { + return nil, errors.New("missing service port") + } + + // Set default domain + if domain == "" { + domain = "local." + } + + if err := validateFQDN(domain); err != nil { + return nil, fmt.Errorf("domain %q is not a fully-qualified domain name: %w", domain, err) + } + + // Get host information if no host is specified. + if hostName == "" { + var err error + + hostName, err = os.Hostname() + if err != nil { + return nil, fmt.Errorf("could not determine host: %w", err) + } + + hostName += "." + } + + if err := validateFQDN(hostName); err != nil { + return nil, fmt.Errorf("hostName %q is not a fully-qualified domain name: %w", hostName, err) + } + + if len(ips) == 0 { + var err error + + ips, err = net.LookupIP(util.TrimDot(hostName)) + if err != nil { + // Try appending the host domain suffix and lookup again + // (required for Linux-based hosts) + tmpHostName := fmt.Sprintf("%s%s", hostName, domain) + + ips, err = net.LookupIP(util.TrimDot(tmpHostName)) + + if err != nil { + return nil, fmt.Errorf("could not determine host IP addresses for %s", hostName) + } + } + } + + for _, ip := range ips { + if ip.To4() == nil && ip.To16() == nil { + return nil, fmt.Errorf("invalid IP address in IPs list: %v", ip) + } + } + + return &MDNSService{ + Instance: instance, + Service: service, + Domain: domain, + HostName: hostName, + Port: port, + IPs: ips, + TXT: txt, + TTL: DefaultTTL, + serviceAddr: fmt.Sprintf("%s.%s.", util.TrimDot(service), util.TrimDot(domain)), + instanceAddr: fmt.Sprintf("%s.%s.%s.", instance, util.TrimDot(service), util.TrimDot(domain)), + enumAddr: fmt.Sprintf("_services._dns-sd._udp.%s.", util.TrimDot(domain)), + }, nil +} + +// Records returns DNS records in response to a DNS question. +func (m *MDNSService) Records(q dns.Question) []dns.RR { + switch q.Name { + case m.enumAddr: + return m.serviceEnum(q) + case m.serviceAddr: + return m.serviceRecords(q) + case m.instanceAddr: + return m.instanceRecords(q) + case m.HostName: + if q.Qtype == dns.TypeA || q.Qtype == dns.TypeAAAA { + return m.instanceRecords(q) + } + + fallthrough + default: + return nil + } +} + +func (m *MDNSService) serviceEnum(q dns.Question) []dns.RR { + switch q.Qtype { + case dns.TypeANY: + fallthrough + case dns.TypePTR: + rr := &dns.PTR{ + Hdr: dns.RR_Header{ //nolint:nosnakecase + Name: q.Name, + Rrtype: dns.TypePTR, + Class: dns.ClassINET, + Ttl: atomic.LoadUint32(&m.TTL), + }, + Ptr: m.serviceAddr, + } + + return []dns.RR{rr} + default: + return nil + } +} + +// serviceRecords is called when the query matches the service name. +func (m *MDNSService) serviceRecords(q dns.Question) []dns.RR { + switch q.Qtype { + case dns.TypeANY: + fallthrough + case dns.TypePTR: + // Build a PTR response for the service + rr := &dns.PTR{ + Hdr: dns.RR_Header{ //nolint:nosnakecase + Name: q.Name, + Rrtype: dns.TypePTR, + Class: dns.ClassINET, + Ttl: atomic.LoadUint32(&m.TTL), + }, + Ptr: m.instanceAddr, + } + servRec := []dns.RR{rr} + + // Get the instance records + instRecs := m.instanceRecords(dns.Question{ + Name: m.instanceAddr, + Qtype: dns.TypeANY, + }) + + // Return the service record with the instance records + return append(servRec, instRecs...) + default: + return nil + } +} + +// serviceRecords is called when the query matches the instance name. +func (m *MDNSService) instanceRecords(question dns.Question) []dns.RR { //nolint:funlen + switch question.Qtype { + case dns.TypeANY: + // Get the SRV, which includes A and AAAA + recs := m.instanceRecords(dns.Question{ + Name: m.instanceAddr, + Qtype: dns.TypeSRV, + }) + + // Add the TXT record + recs = append(recs, m.instanceRecords(dns.Question{ + Name: m.instanceAddr, + Qtype: dns.TypeTXT, + })...) + + return recs + + case dns.TypeA: + var rr []dns.RR + + for _, ip := range m.IPs { + if ip4 := ip.To4(); ip4 != nil { + rr = append(rr, &dns.A{ + Hdr: dns.RR_Header{ //nolint:nosnakecase + Name: m.HostName, + Rrtype: dns.TypeA, + Class: dns.ClassINET, + Ttl: atomic.LoadUint32(&m.TTL), + }, + A: ip4, + }) + } + } + + return rr + + case dns.TypeAAAA: + var rr []dns.RR + + for _, ip := range m.IPs { + if ip.To4() != nil { + // TODO(reddaly): IPv4 addresses could be encoded in IPv6 format and + // putinto AAAA records, but the current logic puts ipv4-encodable + // addresses into the A records exclusively. Perhaps this should be + // configurable? + continue + } + + if ip16 := ip.To16(); ip16 != nil { + rr = append(rr, &dns.AAAA{ + Hdr: dns.RR_Header{ //nolint:nosnakecase + Name: m.HostName, + Rrtype: dns.TypeAAAA, + Class: dns.ClassINET, + Ttl: atomic.LoadUint32(&m.TTL), + }, + AAAA: ip16, + }) + } + } + + return rr + + case dns.TypeSRV: + // Create the SRV Record + srv := &dns.SRV{ + Hdr: dns.RR_Header{ //nolint:nosnakecase + Name: question.Name, + Rrtype: dns.TypeSRV, + Class: dns.ClassINET, + Ttl: atomic.LoadUint32(&m.TTL), + }, + Priority: 10, + Weight: 1, + Port: uint16(m.Port), //nolint:gosec + Target: m.HostName, + } + recs := []dns.RR{srv} + + // Add the A record + recs = append(recs, m.instanceRecords(dns.Question{ + Name: m.instanceAddr, + Qtype: dns.TypeA, + })...) + + // Add the AAAA record + recs = append(recs, m.instanceRecords(dns.Question{ + Name: m.instanceAddr, + Qtype: dns.TypeAAAA, + })...) + + return recs + + case dns.TypeTXT: + txt := &dns.TXT{ + Hdr: dns.RR_Header{ //nolint:nosnakecase + Name: question.Name, + Rrtype: dns.TypeTXT, + Class: dns.ClassINET, + Ttl: atomic.LoadUint32(&m.TTL), + }, + Txt: m.TXT, + } + + return []dns.RR{txt} + } + + return nil +} + +// GetServiceAddr returns the service address. +func (m *MDNSService) GetServiceAddr() string { + return m.serviceAddr +} + +// TestMDNSService is used for tests. Don't use. +var TestMDNSService = MDNSService{ //nolint:gochecknoglobals + serviceAddr: "_foobar._tcp.local.", + Domain: "local", +} diff --git a/registry/mdns/zone/zone_test.go b/registry/mdns/zone/zone_test.go new file mode 100644 index 00000000..c15bf4b1 --- /dev/null +++ b/registry/mdns/zone/zone_test.go @@ -0,0 +1,279 @@ +package zone + +import ( + "bytes" + "net" + "reflect" + "testing" + + "github.com/miekg/dns" +) + +func MakeTestService(t *testing.T) *MDNSService { + t.Helper() + return makeServiceWithServiceName(t, "_http._tcp") +} + +func makeServiceWithServiceName(t *testing.T, service string) *MDNSService { + t.Helper() + + m, err := NewMDNSService( + "hostname", + service, + "local.", + "testhost.", + 80, // port + []net.IP{net.IP([]byte{192, 168, 0, 42}), net.ParseIP("2620:0:1000:1900:b0c2:d0b2:c411:18bc")}, + []string{"Local web server"}, + ) // TXT + if err != nil { + t.Fatalf("err: %v", err) + } + + return m +} + +func TestNewMDNSService_BadParams(t *testing.T) { + for _, test := range []struct { + testName string + hostName string + domain string + }{ + { + "NewMDNSService should fail when passed hostName that is not a legal fully-qualified domain name", + "hostname", // not legal FQDN - should be "hostname." or "hostname.local.", etc. + "local.", // legal + }, + { + "NewMDNSService should fail when passed domain that is not a legal fully-qualified domain name", + "hostname.", // legal + "local", // should be "local." + }, + } { + _, err := NewMDNSService( + "instance name", + "_http._tcp", + test.domain, + test.hostName, + 80, // port + []net.IP{net.IP([]byte{192, 168, 0, 42})}, + []string{"Local web server"}) // TXT + if err == nil { + t.Fatalf("%s: error expected, but got none", test.testName) + } + } +} + +func TestMDNSService_BadAddr(t *testing.T) { + s := MakeTestService(t) + q := dns.Question{ + Name: "random", + Qtype: dns.TypeANY, + } + recs := s.Records(q) + if len(recs) != 0 { + t.Fatalf("bad: %v", recs) + } +} + +func TestMDNSService_ServiceAddr(t *testing.T) { + s := MakeTestService(t) + q := dns.Question{ + Name: "_http._tcp.local.", + Qtype: dns.TypeANY, + } + recs := s.Records(q) + if got, want := len(recs), 5; got != want { + t.Fatalf("got %d records, want %d: %v", got, want, recs) + } + + if ptr, ok := recs[0].(*dns.PTR); !ok { + t.Errorf("recs[0] should be PTR record, got: %v, all records: %v", recs[0], recs) + } else if got, want := ptr.Ptr, "hostname._http._tcp.local."; got != want { + t.Fatalf("bad PTR record %v: got %v, want %v", ptr, got, want) + } + + if _, ok := recs[1].(*dns.SRV); !ok { + t.Errorf("recs[1] should be SRV record, got: %v, all reccords: %v", recs[1], recs) + } + if _, ok := recs[2].(*dns.A); !ok { + t.Errorf("recs[2] should be A record, got: %v, all records: %v", recs[2], recs) + } + if _, ok := recs[3].(*dns.AAAA); !ok { + t.Errorf("recs[3] should be AAAA record, got: %v, all records: %v", recs[3], recs) + } + if _, ok := recs[4].(*dns.TXT); !ok { + t.Errorf("recs[4] should be TXT record, got: %v, all records: %v", recs[4], recs) + } + + q.Qtype = dns.TypePTR + if recs2 := s.Records(q); !reflect.DeepEqual(recs, recs2) { + t.Fatalf("PTR question should return same result as ANY question: ANY => %v, PTR => %v", recs, recs2) + } +} + +func TestMDNSService_InstanceAddr_ANY(t *testing.T) { + s := MakeTestService(t) + q := dns.Question{ + Name: "hostname._http._tcp.local.", + Qtype: dns.TypeANY, + } + recs := s.Records(q) + if len(recs) != 4 { + t.Fatalf("bad: %v", recs) + } + if _, ok := recs[0].(*dns.SRV); !ok { + t.Fatalf("bad: %v", recs[0]) + } + if _, ok := recs[1].(*dns.A); !ok { + t.Fatalf("bad: %v", recs[1]) + } + if _, ok := recs[2].(*dns.AAAA); !ok { + t.Fatalf("bad: %v", recs[2]) + } + if _, ok := recs[3].(*dns.TXT); !ok { + t.Fatalf("bad: %v", recs[3]) + } +} + +func TestMDNSService_InstanceAddr_SRV(t *testing.T) { + s := MakeTestService(t) + q := dns.Question{ + Name: "hostname._http._tcp.local.", + Qtype: dns.TypeSRV, + } + recs := s.Records(q) + if len(recs) != 3 { + t.Fatalf("bad: %v", recs) + } + srv, ok := recs[0].(*dns.SRV) + if !ok { + t.Fatalf("bad: %v", recs[0]) + } + if _, ok := recs[1].(*dns.A); !ok { + t.Fatalf("bad: %v", recs[1]) + } + if _, ok := recs[2].(*dns.AAAA); !ok { + t.Fatalf("bad: %v", recs[2]) + } + + if srv.Port != uint16(s.Port) { + t.Fatalf("bad: %v", recs[0]) + } +} + +func TestMDNSService_InstanceAddr_A(t *testing.T) { + s := MakeTestService(t) + q := dns.Question{ + Name: "hostname._http._tcp.local.", + Qtype: dns.TypeA, + } + recs := s.Records(q) + if len(recs) != 1 { + t.Fatalf("bad: %v", recs) + } + a, ok := recs[0].(*dns.A) + if !ok { + t.Fatalf("bad: %v", recs[0]) + } + if !bytes.Equal(a.A, []byte{192, 168, 0, 42}) { + t.Fatalf("bad: %v", recs[0]) + } +} + +func TestMDNSService_InstanceAddr_AAAA(t *testing.T) { + s := MakeTestService(t) + q := dns.Question{ + Name: "hostname._http._tcp.local.", + Qtype: dns.TypeAAAA, + } + recs := s.Records(q) + if len(recs) != 1 { + t.Fatalf("bad: %v", recs) + } + a4, ok := recs[0].(*dns.AAAA) + if !ok { + t.Fatalf("bad: %v", recs[0]) + } + ip6 := net.ParseIP("2620:0:1000:1900:b0c2:d0b2:c411:18bc") + if got := len(ip6); got != net.IPv6len { + t.Fatalf("test IP failed to parse (len = %d, want %d)", got, net.IPv6len) + } + + if !ip6.Equal(a4.AAAA) { + t.Fatalf("bad: %v", recs[0]) + } +} + +func TestMDNSService_InstanceAddr_TXT(t *testing.T) { + s := MakeTestService(t) + q := dns.Question{ + Name: "hostname._http._tcp.local.", + Qtype: dns.TypeTXT, + } + recs := s.Records(q) + if len(recs) != 1 { + t.Fatalf("bad: %v", recs) + } + txt, ok := recs[0].(*dns.TXT) + if !ok { + t.Fatalf("bad: %v", recs[0]) + } + if got, want := txt.Txt, s.TXT; !reflect.DeepEqual(got, want) { + t.Fatalf("TXT record mismatch for %v: got %v, want %v", recs[0], got, want) + } +} + +func TestMDNSService_HostNameQuery(t *testing.T) { + s := MakeTestService(t) + for _, test := range []struct { + q dns.Question + want []dns.RR + }{ + { + dns.Question{Name: "testhost.", Qtype: dns.TypeA}, + []dns.RR{&dns.A{ + Hdr: dns.RR_Header{ //nolint:nosnakecase + Name: "testhost.", + Rrtype: dns.TypeA, + Class: dns.ClassINET, + Ttl: 120, + }, + A: net.IP([]byte{192, 168, 0, 42}), + }}, + }, + { + dns.Question{Name: "testhost.", Qtype: dns.TypeAAAA}, + []dns.RR{&dns.AAAA{ + Hdr: dns.RR_Header{ //nolint:nosnakecase + Name: "testhost.", + Rrtype: dns.TypeAAAA, + Class: dns.ClassINET, + Ttl: 120, + }, + AAAA: net.ParseIP("2620:0:1000:1900:b0c2:d0b2:c411:18bc"), + }}, + }, + } { + if got := s.Records(test.q); !reflect.DeepEqual(got, test.want) { + t.Errorf("hostname query failed: s.Records(%v) = %v, want %v", test.q, got, test.want) + } + } +} + +func TestMDNSService_serviceEnum_PTR(t *testing.T) { + s := MakeTestService(t) + q := dns.Question{ + Name: "_services._dns-sd._udp.local.", + Qtype: dns.TypePTR, + } + recs := s.Records(q) + if len(recs) != 1 { + t.Fatalf("bad: %v", recs) + } + if ptr, ok := recs[0].(*dns.PTR); !ok { + t.Errorf("recs[0] should be PTR record, got: %v, all records: %v", recs[0], recs) + } else if got, want := ptr.Ptr, "_http._tcp.local."; got != want { + t.Fatalf("bad PTR record %v: got %v, want %v", ptr, got, want) + } +} diff --git a/registry/memory/go.mod b/registry/memory/go.mod index f10c92f2..f8ceef85 100644 --- a/registry/memory/go.mod +++ b/registry/memory/go.mod @@ -3,10 +3,10 @@ module github.com/go-orb/plugins/registry/memory go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320235901-3af29c3a3b34 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122813-09813c7b9d65 github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.10.0 ) diff --git a/registry/memory/go.sum b/registry/memory/go.sum index 6cb2437e..3f4d994a 100644 --- a/registry/memory/go.sum +++ b/registry/memory/go.sum @@ -5,14 +5,14 @@ github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2L github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 h1:X3NixTLN7+Oqn674kP8t96ztHUspl1CEliCY1bD8Kzk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:w2LKGIQfvocVKtQPmxoGi36ND4cKXicVlfpORu3Irjs= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320235901-3af29c3a3b34 h1:LV9i2413Zr0kkoaNrEJB+uMEu5MXqt+IOL3BUwPq6mo= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:C2DhKbnImH0vAc4+iyLcY0fADmBaIJ2y1u8MxmQSkpw= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 h1:Fj2tX19g5TxjS9pHyDV4ZMLkZYW4cuNJ6yh149HRJ84= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:U4rbrSlCGhQaiJxl4GRwIQLUv+Cg8og9NEEInd9j8ww= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122813-09813c7b9d65 h1:InnSP/542m8MeczOjL14qtnpeGu14od2PAtedfRPrg8= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:qUq39uHPQ6qZZxNFtH3IPb01vWESqwSJrzUvrzAiBzc= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= diff --git a/registry/memory/memory.go b/registry/memory/memory.go index f1194985..84af13b5 100644 --- a/registry/memory/memory.go +++ b/registry/memory/memory.go @@ -4,6 +4,8 @@ package memory import ( "context" "errors" + "slices" + "strings" "sync" "time" @@ -17,19 +19,9 @@ import ( // This is here to make sure Registry implements registry.Registry. var _ registry.Registry = (*Registry)(nil) -type node struct { - *registry.Node - +type serviceNode struct { + registry.ServiceNode LastSeen time.Time - TTL time.Duration -} - -type record struct { - Name string - Version string - Metadata map[string]string - Nodes map[string]*node - Endpoints []*registry.Endpoint } type dataStore struct { @@ -37,13 +29,24 @@ type dataStore struct { logger log.Logger - Records map[string]map[string]*record + Records map[string]serviceNode Watchers map[string]*watcher startOnce sync.Once sync.RWMutex } +func nodeKey(s registry.ServiceNode) string { + return strings.Join([]string{ + s.Namespace, + s.Region, + s.Name, + s.Version, + s.Scheme, + s.Address, + }, ":") +} + func (d *dataStore) Start(ctx context.Context) { d.startOnce.Do(func() { go d.ttlPrune(ctx) @@ -60,16 +63,22 @@ func (d *dataStore) ttlPrune(ctx context.Context) { return case <-prune.C: d.Lock() - for name, records := range d.Records { - for version, record := range records { - for id, n := range record.Nodes { - if n.TTL != 0 && time.Since(n.LastSeen) > n.TTL { - d.logger.Debug("Registry TTL expired for node of service", "node", n.ID, "service", name) - delete(d.Records[name][version].Nodes, id) - } - } + toDelete := []string{} + + for key, record := range d.Records { + if record.ServiceNode.TTL != 0 && time.Since(record.LastSeen) > record.ServiceNode.TTL { + d.logger.Debug("Registry TTL expired for node of service", "address", record.ServiceNode.Address, "service", record.ServiceNode.Name) + + go d.SendEvent(®istry.Result{Action: registry.Delete, Node: record.ServiceNode}) + + toDelete = append(toDelete, key) } } + + for _, key := range toDelete { + delete(d.Records, key) + } + d.Unlock() } } @@ -86,7 +95,7 @@ func (d *dataStore) SendEvent(r *registry.Result) { for _, w := range watchers { select { - case <-w.exit: + case <-w.ctx.Done(): d.Lock() delete(d.Watchers, w.id) d.Unlock() @@ -102,9 +111,6 @@ func (d *dataStore) SendEvent(r *registry.Result) { // Registry is the memory registry for go-orb. type Registry struct { - serviceName string - serviceVersion string - config Config logger log.Logger @@ -112,16 +118,6 @@ type Registry struct { dataStore *dataStore } -// ServiceName returns the configured name of this service. -func (c *Registry) ServiceName() string { - return c.serviceName -} - -// ServiceVersion returns the configured version of this service. -func (c *Registry) ServiceVersion() string { - return c.serviceVersion -} - // Start starts the registry. func (c *Registry) Start(ctx context.Context) error { c.dataStore.Start(ctx) @@ -145,193 +141,127 @@ func (c *Registry) Type() string { } // Deregister deregisters a service within the registry. -func (c *Registry) Deregister(s *registry.Service, _ ...registry.DeregisterOption) error { +func (c *Registry) Deregister(_ context.Context, s registry.ServiceNode) error { c.dataStore.Lock() defer c.dataStore.Unlock() - //nolint:nestif - if _, ok := c.dataStore.Records[s.Name]; ok { - if _, ok := c.dataStore.Records[s.Name][s.Version]; ok { - for _, n := range s.Nodes { - if _, ok := c.dataStore.Records[s.Name][s.Version].Nodes[n.ID]; ok { - c.logger.Trace("Registry removed node from service", "name", s.Name, "version", s.Version) - delete(c.dataStore.Records[s.Name][s.Version].Nodes, n.ID) - } - } + key := nodeKey(s) - if len(c.dataStore.Records[s.Name][s.Version].Nodes) == 0 { - delete(c.dataStore.Records[s.Name], s.Version) - c.logger.Trace("Registry removed service", "name", s.Name, "version", s.Version) - } - } + if _, ok := c.dataStore.Records[key]; ok { + c.logger.Debug("Registry deregister service", "name", s.Name) + delete(c.dataStore.Records, key) - if len(c.dataStore.Records[s.Name]) == 0 { - delete(c.dataStore.Records, s.Name) - c.logger.Trace("Registry removed service", "name", s.Name) - } + go c.dataStore.SendEvent(®istry.Result{Action: registry.Delete, Node: s}) - go c.dataStore.SendEvent(®istry.Result{Action: "delete", Service: s}) + return nil } return nil } // Register registers a service within the registry. -// -//nolint:funlen -func (c *Registry) Register(service *registry.Service, opts ...registry.RegisterOption) error { +func (c *Registry) Register(_ context.Context, s registry.ServiceNode) error { c.dataStore.Lock() defer c.dataStore.Unlock() - var options registry.RegisterOptions - for _, o := range opts { - o(&options) - } - - r := serviceToRecord(service, options.TTL) - - if _, ok := c.dataStore.Records[service.Name]; !ok { - c.dataStore.Records[service.Name] = make(map[string]*record) - } + key := nodeKey(s) + if _, ok := c.dataStore.Records[key]; ok { + c.logger.Debug("Registry updated service", "name", s.Name, "version", s.Version) - if _, ok := c.dataStore.Records[service.Name][service.Version]; !ok { - // New service - store it and we're done - c.dataStore.Records[service.Name][service.Version] = r - c.logger.Trace("Registry added new service", "name", service.Name, "version", service.Version) + c.dataStore.Records[key] = serviceNode{ + ServiceNode: s, + LastSeen: time.Now(), + } - go c.dataStore.SendEvent(®istry.Result{Action: "create", Service: service}) + go c.dataStore.SendEvent(®istry.Result{Action: registry.Update, Node: s}) return nil } - // Existing service - update record - existingRecord := c.dataStore.Records[service.Name][service.Version] - - // Update the service metadata - existingRecord.Metadata = make(map[string]string) - for k, v := range service.Metadata { - existingRecord.Metadata[k] = v + c.dataStore.Records[key] = serviceNode{ + ServiceNode: s, + LastSeen: time.Now(), } - // Update the endpoints - existingRecord.Endpoints = service.Endpoints + c.logger.Debug("Registry registered service", "name", s.Name, "version", s.Version) - // Track if we made any changes - changes := false + go c.dataStore.SendEvent(®istry.Result{Action: registry.Create, Node: s}) - // Handle nodes - for _, newNode := range service.Nodes { - if existingNode, ok := existingRecord.Nodes[newNode.ID]; !ok { //nolint:nestif - // This is a new node, add it - changes = true - metadata := make(map[string]string) + return nil +} - for k, v := range newNode.Metadata { - metadata[k] = v - } +// GetService returns a service from the registry. +func (c *Registry) GetService(_ context.Context, namespace, region, name string, schemes []string) ([]registry.ServiceNode, error) { + c.dataStore.RLock() + defer c.dataStore.RUnlock() - existingRecord.Nodes[newNode.ID] = &node{ - Node: ®istry.Node{ - ID: newNode.ID, - Address: newNode.Address, - Transport: newNode.Transport, - Metadata: metadata, - }, - TTL: options.TTL, - LastSeen: time.Now(), - } - } else { - // This is an existing node, update it - if existingNode.Address != newNode.Address { - existingNode.Address = newNode.Address - changes = true - } + services := []registry.ServiceNode{} - if existingNode.Transport != newNode.Transport { - existingNode.Transport = newNode.Transport - changes = true - } + for _, record := range c.dataStore.Records { + if name != "" && record.Name != name { + continue + } - // Update metadata - for k, v := range newNode.Metadata { - if existingValue, ok := existingNode.Metadata[k]; !ok || existingValue != v { - if existingNode.Metadata == nil { - existingNode.Metadata = make(map[string]string) - } + if namespace != "" && record.Namespace != namespace { + continue + } - existingNode.Metadata[k] = v - changes = true - } - } + if region != "" && record.Region != region { + continue + } - // Always update TTL and LastSeen - existingNode.TTL = options.TTL - existingNode.LastSeen = time.Now() + if len(schemes) > 0 && !slices.Contains(schemes, record.Scheme) { + continue } - } - // If we made changes or this is a regular TTL refresh, send an update - if changes { - c.logger.Debug("Updated service", "name", service.Name, "version", service.Version) - } else { - c.logger.Debug("Refreshed service TTL", "name", service.Name, "version", service.Version) + services = append(services, record.ServiceNode) } - // Send an update event regardless of changes to maintain expected behavior - go c.dataStore.SendEvent(®istry.Result{Action: "update", Service: service}) - - return nil -} - -// GetService returns a service from the registry. -func (c *Registry) GetService(name string, _ ...registry.GetOption) ([]*registry.Service, error) { - c.dataStore.RLock() - defer c.dataStore.RUnlock() - - records, ok := c.dataStore.Records[name] - if !ok { + if len(services) == 0 { return nil, registry.ErrNotFound } - services := make([]*registry.Service, len(c.dataStore.Records[name])) - i := 0 - - for _, record := range records { - services[i] = recordToService(record) - i++ - } - return services, nil } // ListServices lists services within the registry. -func (c *Registry) ListServices(_ ...registry.ListOption) ([]*registry.Service, error) { +func (c *Registry) ListServices(_ context.Context, namespace, region string, schemes []string) ([]registry.ServiceNode, error) { c.dataStore.RLock() defer c.dataStore.RUnlock() - var services []*registry.Service + services := []registry.ServiceNode{} + + for _, record := range c.dataStore.Records { + if namespace != "" && record.Namespace != namespace { + continue + } - for _, records := range c.dataStore.Records { - for _, record := range records { - services = append(services, recordToService(record)) + if region != "" && record.Region != region { + continue } + + if len(schemes) > 0 && !slices.Contains(schemes, record.Scheme) { + continue + } + + services = append(services, record.ServiceNode) } return services, nil } // Watch returns a Watcher which you can watch on. -func (c *Registry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { +func (c *Registry) Watch(ctx context.Context, opts ...registry.WatchOption) (registry.Watcher, error) { var wo registry.WatchOptions for _, o := range opts { o(&wo) } w := &watcher{ - exit: make(chan bool), - res: make(chan *registry.Result), - id: uuid.New().String(), - wo: wo, + ctx: ctx, + res: make(chan *registry.Result), + id: uuid.New().String(), + wo: wo, } c.dataStore.Lock() @@ -343,8 +273,6 @@ func (c *Registry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) // Provide creates a new memory registry. func Provide( - name string, - version string, datas map[string]any, _ *types.Components, logger log.Logger, @@ -356,7 +284,7 @@ func Provide( return registry.Type{}, err } - reg := New(name, version, cfg, logger) + reg := New(cfg, logger) return registry.Type{Registry: reg}, nil } @@ -365,21 +293,19 @@ func Provide( var store *dataStore // New creates a new memory registry. -func New(serviceName string, serviceVersion string, cfg Config, logger log.Logger) *Registry { +func New(cfg Config, logger log.Logger) *Registry { if store == nil { store = &dataStore{ config: cfg, logger: logger, - Records: make(map[string]map[string]*record), + Records: make(map[string]serviceNode), Watchers: make(map[string]*watcher), } } instance := &Registry{ - serviceName: serviceName, - serviceVersion: serviceVersion, - config: cfg, - logger: logger, + config: cfg, + logger: logger, dataStore: store, } diff --git a/registry/memory/memory_test.go b/registry/memory/memory_test.go index 3bf39735..3cd3b0c2 100644 --- a/registry/memory/memory_test.go +++ b/registry/memory/memory_test.go @@ -14,31 +14,31 @@ import ( "github.com/go-orb/plugins/registry/tests" ) -func createRegistries() (*tests.TestSuite, func() error, error) { +func createSuite() (*tests.TestSuite, func() error, error) { ctx := context.Background() - logger, err := log.New() + logger, err := log.New(log.WithLevel(log.LevelTrace)) if err != nil { log.Error("failed to create logger", "err", err) return nil, func() error { return nil }, err } cfg1 := NewConfig() - reg1 := New("orb.service.test1", "unset", cfg1, logger) + reg1 := New(cfg1, logger) if err := reg1.Start(ctx); err != nil { log.Error("failed to connect registry one to Consul server", "err", err) return nil, func() error { return nil }, err } cfg2 := NewConfig() - reg2 := New("orb.service.test2", "unset", cfg2, logger) + reg2 := New(cfg2, logger) if err := reg2.Start(ctx); err != nil { log.Error("failed to connect registry two to Consul server", "err", err) return nil, func() error { return nil }, err } cfg3 := NewConfig() - reg3 := New("orb.service.test3", "unset", cfg3, logger) + reg3 := New(cfg3, logger) if err := reg3.Start(ctx); err != nil { log.Error("failed to connect registry three to Consul server", "err", err) return nil, func() error { return nil }, err @@ -50,11 +50,11 @@ func createRegistries() (*tests.TestSuite, func() error, error) { return nil } - return tests.CreateSuite(logger, []registry.Registry{reg1, reg2, reg3}, 0, 0), cleanup, nil + return tests.CreateSuite(logger, []registry.Registry{reg1, reg2, reg3}, 0), cleanup, nil } func TestSuite(t *testing.T) { - s, cleanup, err := createRegistries() + s, cleanup, err := createSuite() require.NoError(t, err, "while creating a server") // Run the tests. @@ -64,7 +64,7 @@ func TestSuite(t *testing.T) { } func BenchmarkGetService(b *testing.B) { - s, cleanup, err := createRegistries() + s, cleanup, err := createSuite() require.NoError(b, err, "while creating a server") s.BenchmarkGetService(b) @@ -73,7 +73,7 @@ func BenchmarkGetService(b *testing.B) { } func BenchmarkParallelGetService(b *testing.B) { - s, cleanup, err := createRegistries() + s, cleanup, err := createSuite() require.NoError(b, err, "while creating a server") s.BenchmarkGetService(b) @@ -82,7 +82,7 @@ func BenchmarkParallelGetService(b *testing.B) { } func BenchmarkGetServiceWithNoNodes(b *testing.B) { - s, cleanup, err := createRegistries() + s, cleanup, err := createSuite() require.NoError(b, err, "while creating a server") s.BenchmarkGetServiceWithNoNodes(b) diff --git a/registry/memory/util.go b/registry/memory/util.go deleted file mode 100644 index 35d7950f..00000000 --- a/registry/memory/util.go +++ /dev/null @@ -1,72 +0,0 @@ -package memory - -import ( - "maps" - "slices" - "time" - - "github.com/go-orb/go-orb/registry" -) - -func serviceToRecord(s *registry.Service, ttl time.Duration) *record { - nodes := make(map[string]*node, len(s.Nodes)) - for _, n := range s.Nodes { - nodes[n.ID] = &node{ - Node: n, - TTL: ttl, - LastSeen: time.Now(), - } - } - - return &record{ - Name: s.Name, - Version: s.Version, - Metadata: maps.Clone(s.Metadata), - Nodes: nodes, - Endpoints: slices.Clone(s.Endpoints), - } -} - -func recordToService(inRecord *record) *registry.Service { - endpoints := make([]*registry.Endpoint, len(inRecord.Endpoints)) - - for i, e := range inRecord.Endpoints { - request := new(registry.Value) - if e.Request != nil { - *request = *e.Request - } - - response := new(registry.Value) - if e.Response != nil { - *response = *e.Response - } - - endpoints[i] = ®istry.Endpoint{ - Name: e.Name, - Request: request, - Response: response, - Metadata: maps.Clone(e.Metadata), - } - } - - nodes := make([]*registry.Node, len(inRecord.Nodes)) - i := 0 - - for _, n := range inRecord.Nodes { - nodes[i] = ®istry.Node{ - ID: n.ID, - Address: n.Address, - Transport: n.Transport, - Metadata: maps.Clone(n.Metadata), - } - i++ - } - - return ®istry.Service{ - Name: inRecord.Name, - Version: inRecord.Version, - Metadata: maps.Clone(inRecord.Metadata), - Endpoints: endpoints, - Nodes: nodes, - } -} diff --git a/registry/memory/watcher.go b/registry/memory/watcher.go index f39e31a6..07f7ea50 100644 --- a/registry/memory/watcher.go +++ b/registry/memory/watcher.go @@ -1,40 +1,31 @@ package memory import ( + "context" "errors" "github.com/go-orb/go-orb/registry" ) type watcher struct { - wo registry.WatchOptions - res chan *registry.Result - exit chan bool - id string + ctx context.Context + + wo registry.WatchOptions + res chan *registry.Result + id string } func (m *watcher) Next() (*registry.Result, error) { for { select { case r := <-m.res: - if len(m.wo.Service) > 0 && m.wo.Service != r.Service.Name { + if len(m.wo.Service) > 0 && m.wo.Service != r.Node.Name { continue } return r, nil - case <-m.exit: + case <-m.ctx.Done(): return nil, errors.New("watcher stopped") } } } - -func (m *watcher) Stop() error { - select { - case <-m.exit: - return nil - default: - close(m.exit) - } - - return nil -} diff --git a/registry/regutil/cache/cache.go b/registry/regutil/cache/cache.go index eeb2967f..73d5d7ea 100644 --- a/registry/regutil/cache/cache.go +++ b/registry/regutil/cache/cache.go @@ -4,22 +4,16 @@ package cache import ( "context" "errors" + "fmt" + "slices" "sync" "github.com/go-orb/go-orb/log" "github.com/go-orb/go-orb/registry" ) -type node struct { - registry.Node -} - -type record struct { - Name string - Version string - Metadata map[string]string - Nodes map[string]node - Endpoints []registry.Endpoint +func nodeKey(s registry.ServiceNode) string { + return fmt.Sprintf("%s:%s:%s:%s:%s:%s", s.Namespace, s.Region, s.Name, s.Version, s.Scheme, s.Address) } type dataStore struct { @@ -27,7 +21,7 @@ type dataStore struct { registry registry.Registry - Records map[string]map[string]record + Records map[string]registry.ServiceNode watcher registry.Watcher watchCancel context.CancelFunc @@ -37,29 +31,39 @@ type dataStore struct { } // populate initializes the cache with services from the registry. -func (d *dataStore) populate() { - services, err := d.registry.ListServices() +func (d *dataStore) populate(ctx context.Context) { + services, err := d.registry.ListServices(ctx, "", "", nil) if err != nil { d.logger.Warn("Failed to list services when populating cache", "error", err) return } - store.Lock() - defer store.Unlock() - + // Create a map to track unique service names + serviceNames := make(map[string]registry.ServiceNode) for _, service := range services { - fullServices, err := d.registry.GetService(service.Name) + serviceNames[nodeKey(service)] = service + } + + d.Lock() + defer d.Unlock() + + // Fetch full details for each service + for _, svc := range serviceNames { + serviceNodes, err := d.registry.GetService(ctx, svc.Namespace, svc.Region, svc.Name, nil) if err != nil { - d.logger.Warn("Failed to get service details when populating cache", "name", service.Name, "error", err) + if !errors.Is(err, registry.ErrNotFound) { + d.logger.Warn("Failed to get service details when populating cache", "name", svc.Name, "error", err) + } + continue } - for _, fullService := range fullServices { - d.registerServiceInternal(fullService) + for _, serviceNode := range serviceNodes { + d.registerServiceNodeInternal(serviceNode) } } - d.logger.Debug("Populated cache with services from registry") + d.logger.Debug("Populated with services from registry") } // startWatching begins watching a registry for service changes and updates the cache accordingly. @@ -71,16 +75,17 @@ func (d *dataStore) startWatching(ctx context.Context) error { // Start the watcher. var err error - d.watcher, err = d.registry.Watch() + // Create a context for this watcher. + var watchCtx context.Context + watchCtx, d.watchCancel = context.WithCancel(ctx) + + d.watcher, err = d.registry.Watch(watchCtx) if err != nil { return err } - // Create a context for this watcher. - ctx, d.watchCancel = context.WithCancel(ctx) - // Start watching in a goroutine. - go d.watch(ctx) + go d.watch(watchCtx) d.logger.Debug("Started watching registry for changes") @@ -101,7 +106,7 @@ func (d *dataStore) watch(ctx context.Context) { result, err := d.watcher.Next() if err != nil { if errors.Is(err, registry.ErrWatcherStopped) { - d.logger.Debug("Registry watcher stopped") + d.logger.Debug("Registry watcher stopped.") return } @@ -112,10 +117,10 @@ func (d *dataStore) watch(ctx context.Context) { // Process the result based on the action. switch result.Action { - case "create", "update": - d.registerService(result.Service) - case "delete": - if err := d.deregisterService(result.Service); err != nil { + case registry.Create, registry.Update: + d.registerServiceNode(result.Node) + case registry.Delete: + if err := d.deregisterServiceNode(result.Node); err != nil { d.logger.Warn("Error deregistering service from watcher", "error", err) } default: @@ -124,144 +129,44 @@ func (d *dataStore) watch(ctx context.Context) { } } -// deregisterService removes a service from the cache. -func (d *dataStore) deregisterService(service *registry.Service) error { +// deregisterServiceNode removes a service from the cache. +func (d *dataStore) deregisterServiceNode(serviceNode registry.ServiceNode) error { d.Lock() defer d.Unlock() - if service == nil { - return nil - } + key := nodeKey(serviceNode) - // If service doesn't exist in our records, nothing to do - records, ok := d.Records[service.Name] - if !ok { - return nil - } + if _, ok := d.Records[key]; ok { + d.logger.Trace("deregister", "name", serviceNode.Name, "version", serviceNode.Version, "address", serviceNode.Address) + delete(d.Records, key) - // Get the version record if it exists - versionRecord, ok := records[service.Version] - if !ok { return nil } - // Remove the specific nodes - for _, node := range service.Nodes { - delete(versionRecord.Nodes, node.ID) - } - - // Clean up empty records - if len(versionRecord.Nodes) == 0 { - delete(records, service.Version) - - if len(records) == 0 { - d.logger.Trace("Registry removed service completely", "name", service.Name) - delete(d.Records, service.Name) - } - } - return nil } -// registerService adds or updates a service in the cache. -func (d *dataStore) registerService(service *registry.Service) { - d.Lock() - defer d.Unlock() - - d.registerServiceInternal(service) +// registerServiceNode adds or updates a service in the cache. +func (d *dataStore) registerServiceNode(serviceNode registry.ServiceNode) { + d.registerServiceNodeInternal(serviceNode) } -// registerServiceInternal adds or updates a service in the cache (internal method). -func (d *dataStore) registerServiceInternal(service *registry.Service) { - if service == nil { - return - } - - r := serviceToRecord(service) - - // Create map if it doesn't exist. - if _, ok := d.Records[service.Name]; !ok { - d.Records[service.Name] = make(map[string]record) - } - - if _, ok := d.Records[service.Name][service.Version]; !ok { - // New service - store it and we're done. - d.Records[service.Name][service.Version] = r - d.logger.Trace("registry cache added new service", "name", service.Name, "version", service.Version) - - return - } - - // Existing service - update record. - existingRecord := d.Records[service.Name][service.Version] - - // Update the service metadata. - existingRecord.Metadata = make(map[string]string) - for k, v := range service.Metadata { - existingRecord.Metadata[k] = v - } - - // Update the endpoints. - for _, ep := range service.Endpoints { - existingRecord.Endpoints = append(existingRecord.Endpoints, registry.Endpoint{ - Name: ep.Name, - Request: ep.Request, - Response: ep.Response, - Metadata: ep.Metadata, - }) - } - - // Track if we made any changes. - changes := false - - // Handle nodes. - for _, newNode := range service.Nodes { - if existingNode, ok := existingRecord.Nodes[newNode.ID]; !ok { //nolint:nestif - // This is a new node, add it. - changes = true - metadata := make(map[string]string) - - for k, v := range newNode.Metadata { - metadata[k] = v - } - - existingRecord.Nodes[newNode.ID] = node{ - Node: *newNode, - } - } else { - // This is an existing node, update it. - if existingNode.Node.Address != newNode.Address { - existingNode.Node.Address = newNode.Address - changes = true - } - - // Update metadata. - for k, v := range newNode.Metadata { - if existingValue, ok := existingNode.Metadata[k]; !ok || existingValue != v { - if existingNode.Metadata == nil { - existingNode.Metadata = make(map[string]string) - } - - existingNode.Metadata[k] = v - changes = true - } - } - } - } +// registerServiceNodeInternal adds or updates a service in the cache (internal method). +func (d *dataStore) registerServiceNodeInternal(serviceNode registry.ServiceNode) { + d.Lock() + defer d.Unlock() - // If we made changes or this is a regular TTL refresh, send an update. - if changes { - d.logger.Debug("Updated service", "name", service.Name, "version", service.Version) + if _, ok := d.Records[nodeKey(serviceNode)]; ok { + d.Records[nodeKey(serviceNode)] = serviceNode } else { - d.logger.Trace("Refreshed service TTL", "name", service.Name, "version", service.Version) + d.logger.Trace("register", "name", serviceNode.Name, "version", serviceNode.Version, "address", serviceNode.Address) + d.Records[nodeKey(serviceNode)] = serviceNode } - - d.Records[service.Name][service.Version] = existingRecord } //nolint:gochecknoglobals var store = &dataStore{ - Records: make(map[string]map[string]record), + Records: make(map[string]registry.ServiceNode), } func (d *dataStore) Start(ctx context.Context, logger log.Logger, registry registry.Registry) { @@ -275,7 +180,7 @@ func (d *dataStore) Start(ctx context.Context, logger log.Logger, registry regis return } - d.populate() + d.populate(ctx) }) } @@ -300,49 +205,98 @@ func (c *Cache) Start(ctx context.Context) error { // Stop stops the cache and its watcher. func (c *Cache) Stop(_ context.Context) error { + if store.watchCancel != nil { + store.watchCancel() + } + return nil } +// String returns the name of the cache. +func (c *Cache) String() string { + return "registry-cache" +} + // GetService returns a service from the cache. -func (c *Cache) GetService(name string, _ ...registry.GetOption) ([]*registry.Service, error) { +func (c *Cache) GetService(_ context.Context, namespace, region, name string, schemes []string) ([]registry.ServiceNode, error) { store.RLock() defer store.RUnlock() - records, ok := store.Records[name] - if !ok { - return nil, registry.ErrNotFound + services := []registry.ServiceNode{} + + for _, record := range store.Records { + if name != "" && record.Name != name { + continue + } + + if namespace != "" && record.Namespace != namespace { + continue + } + + if region != "" && record.Region != region { + continue + } + + if len(schemes) > 0 && !slices.Contains(schemes, record.Scheme) { + continue + } + + services = append(services, record) } - services := make([]*registry.Service, 0, len(records)) - for _, record := range records { - // Convert record back to service. - services = append(services, recordToService(record)) + if len(services) == 0 { + return nil, registry.ErrNotFound } return services, nil } // ListServices lists services within the cache. -func (c *Cache) ListServices(_ ...registry.ListOption) ([]*registry.Service, error) { +func (c *Cache) ListServices(_ context.Context, namespace, region string, schemes []string) ([]registry.ServiceNode, error) { store.RLock() defer store.RUnlock() - var services []*registry.Service + services := []registry.ServiceNode{} + + for _, record := range store.Records { + if namespace != "" && record.Namespace != namespace { + continue + } + + if region != "" && record.Region != region { + continue + } - for _, records := range store.Records { - for _, record := range records { - services = append(services, recordToService(record)) + if len(schemes) > 0 && !slices.Contains(schemes, record.Scheme) { + continue } + + services = append(services, record) } return services, nil } +// Register registers a service with the cache. +func (c *Cache) Register(ctx context.Context, serviceNode registry.ServiceNode) error { + return c.registry.Register(ctx, serviceNode) +} + +// Deregister deregisters a service with the cache. +func (c *Cache) Deregister(ctx context.Context, serviceNode registry.ServiceNode) error { + return c.registry.Deregister(ctx, serviceNode) +} + +// Watch returns a watcher for the cache. +func (c *Cache) Watch(ctx context.Context, opts ...registry.WatchOption) (registry.Watcher, error) { + return c.registry.Watch(ctx, opts...) +} + // New creates a new registry cache. func New(cfg Config, logger log.Logger, registry registry.Registry) *Cache { return &Cache{ config: cfg, registry: registry, - logger: logger, + logger: logger.With("subcomponent", "registry-cache"), } } diff --git a/registry/regutil/cache/util.go b/registry/regutil/cache/util.go deleted file mode 100644 index beb46e9f..00000000 --- a/registry/regutil/cache/util.go +++ /dev/null @@ -1,86 +0,0 @@ -package cache - -import ( - "maps" - - "github.com/go-orb/go-orb/registry" -) - -func serviceToRecord(service *registry.Service) record { - nodes := make(map[string]node, len(service.Nodes)) - - for _, n := range service.Nodes { - mnode := registry.Node{ - ID: n.ID, - Address: n.Address, - Metadata: maps.Clone(n.Metadata), - Transport: n.Transport, - } - - nodes[n.ID] = node{ - Node: mnode, - } - } - - endpoints := make([]registry.Endpoint, len(service.Endpoints)) - for i, e := range service.Endpoints { - endpoints[i] = registry.Endpoint{ - Name: e.Name, - Request: e.Request, - Response: e.Response, - Metadata: maps.Clone(e.Metadata), - } - } - - return record{ - Name: service.Name, - Version: service.Version, - Metadata: maps.Clone(service.Metadata), - Nodes: nodes, - Endpoints: endpoints, - } -} - -func recordToService(inRecord record) *registry.Service { - endpoints := make([]*registry.Endpoint, len(inRecord.Endpoints)) - - for i, e := range inRecord.Endpoints { - request := new(registry.Value) - if e.Request != nil { - *request = *e.Request - } - - response := new(registry.Value) - if e.Response != nil { - *response = *e.Response - } - - endpoints[i] = ®istry.Endpoint{ - Name: e.Name, - Request: request, - Response: response, - Metadata: maps.Clone(e.Metadata), - } - } - - nodes := make([]*registry.Node, len(inRecord.Nodes)) - i := 0 - - for _, n := range inRecord.Nodes { - nodes[i] = ®istry.Node{ - ID: n.ID, - Address: n.Address, - Transport: n.Transport, - Metadata: maps.Clone(n.Metadata), - } - i++ - } - - return ®istry.Service{ - Name: inRecord.Name, - Version: inRecord.Version, - Metadata: maps.Clone(inRecord.Metadata), - Endpoints: endpoints, - Nodes: nodes, - } -} diff --git a/registry/regutil/go.mod b/registry/regutil/go.mod index ef6e45d6..2de27ce4 100644 --- a/registry/regutil/go.mod +++ b/registry/regutil/go.mod @@ -2,7 +2,7 @@ module github.com/go-orb/plugins/registry/regutil go 1.23.6 -require github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e +require github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 require ( dario.cat/mergo v1.0.1 // indirect diff --git a/registry/regutil/go.sum b/registry/regutil/go.sum index fc1a9761..ee496be1 100644 --- a/registry/regutil/go.sum +++ b/registry/regutil/go.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/registry/regutil/util.go b/registry/regutil/util.go deleted file mode 100644 index 616785d8..00000000 --- a/registry/regutil/util.go +++ /dev/null @@ -1,164 +0,0 @@ -// Package regutil provides utility functions for go-orb. -package regutil - -import ( - "github.com/go-orb/go-orb/registry" -) - -func addNodes(old, neu []*registry.Node) []*registry.Node { - nodes := make([]*registry.Node, len(neu)) - // add all new nodes - for i, n := range neu { - node := *n - nodes[i] = &node - } - - // look at old nodes - for _, o := range old { - var exists bool - - // check against new nodes - for _, n := range nodes { - // ids match then skip - if o.ID == n.ID { - exists = true - break - } - } - - // keep old node - if !exists { - node := *o - nodes = append(nodes, &node) - } - } - - return nodes -} - -func delNodes(old, del []*registry.Node) []*registry.Node { - var nodes []*registry.Node - - for _, o := range old { - var rem bool - - for _, n := range del { - if o.ID == n.ID { - rem = true - break - } - } - - if !rem { - nodes = append(nodes, o) - } - } - - return nodes -} - -// CopyService make a copy of service. -func CopyService(service *registry.Service) *registry.Service { - // copy service - s := new(registry.Service) - *s = *service - - // copy nodes - nodes := make([]*registry.Node, len(service.Nodes)) - - for j, node := range service.Nodes { - n := new(registry.Node) - *n = *node - nodes[j] = n - } - - s.Nodes = nodes - - // copy endpoints - eps := make([]*registry.Endpoint, len(service.Endpoints)) - - for j, ep := range service.Endpoints { - e := new(registry.Endpoint) - *e = *ep - eps[j] = e - } - - s.Endpoints = eps - - return s -} - -// Copy makes a copy of services. -func Copy(current []*registry.Service) []*registry.Service { - services := make([]*registry.Service, len(current)) - for i, service := range current { - services[i] = CopyService(service) - } - - return services -} - -// Merge merges two lists of services and returns a new copy. -func Merge(olist []*registry.Service, nlist []*registry.Service) []*registry.Service { - var srv []*registry.Service - - for _, n := range nlist { - var seen bool - - for _, o := range olist { - if o.Version == n.Version { - sp := new(registry.Service) - // make copy - *sp = *o - // set nodes - sp.Nodes = addNodes(o.Nodes, n.Nodes) - - // mark as seen - seen = true - - srv = append(srv, sp) - - break - } - - sp := new(registry.Service) - // make copy - *sp = *o - srv = append(srv, sp) - } - - if !seen { - srv = append(srv, Copy([]*registry.Service{n})...) - } - } - - return srv -} - -// Remove removes services and returns a new copy. -func Remove(old, del []*registry.Service) []*registry.Service { - var services []*registry.Service - - for _, o := range old { - srv := new(registry.Service) - *srv = *o - - var rem bool - - for _, s := range del { - if srv.Version == s.Version { - srv.Nodes = delNodes(srv.Nodes, s.Nodes) - - if len(srv.Nodes) == 0 { - rem = true - } - } - } - - if !rem { - services = append(services, srv) - } - } - - return services -} diff --git a/registry/regutil/util_test.go b/registry/regutil/util_test.go deleted file mode 100644 index 9f2f3790..00000000 --- a/registry/regutil/util_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package regutil - -import ( - "os" - "testing" - - "github.com/go-orb/go-orb/registry" -) - -func TestRemove(t *testing.T) { - services := []*registry.Service{ - { - Name: "foo", - Version: "1.0.0", - Nodes: []*registry.Node{ - { - ID: "foo-123", - Address: "localhost:9999", - }, - }, - }, - { - Name: "foo", - Version: "1.0.0", - Nodes: []*registry.Node{ - { - ID: "foo-123", - Address: "localhost:6666", - }, - }, - }, - } - - servs := Remove([]*registry.Service{services[0]}, []*registry.Service{services[1]}) - if i := len(servs); i > 0 { - t.Errorf("Expected 0 nodes, got %d: %+v", i, servs) - } - if len(os.Getenv("IN_TRAVIS_CI")) == 0 { - t.Logf("Services %+v", servs) - } -} - -func TestRemoveNodes(t *testing.T) { - services := []*registry.Service{ - { - Name: "foo", - Version: "1.0.0", - Nodes: []*registry.Node{ - { - ID: "foo-123", - Address: "localhost:9999", - }, - { - ID: "foo-321", - Address: "localhost:6666", - }, - }, - }, - { - Name: "foo", - Version: "1.0.0", - Nodes: []*registry.Node{ - { - ID: "foo-123", - Address: "localhost:6666", - }, - }, - }, - } - - nodes := delNodes(services[0].Nodes, services[1].Nodes) - if i := len(nodes); i != 1 { - t.Errorf("Expected only 1 node, got %d: %+v", i, nodes) - } - if len(os.Getenv("IN_TRAVIS_CI")) == 0 { - t.Logf("Nodes %+v", nodes) - } -} diff --git a/registry/tests/go.mod b/registry/tests/go.mod index 7087c019..1ffa77da 100644 --- a/registry/tests/go.mod +++ b/registry/tests/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/registry/tests go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 github.com/stretchr/testify v1.10.0 ) diff --git a/registry/tests/go.sum b/registry/tests/go.sum index 59f4c6a6..c000b6ec 100644 --- a/registry/tests/go.sum +++ b/registry/tests/go.sum @@ -5,8 +5,8 @@ github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2L github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= diff --git a/registry/tests/tests.go b/registry/tests/tests.go index e43fdf68..9fe468b8 100644 --- a/registry/tests/tests.go +++ b/registry/tests/tests.go @@ -2,10 +2,9 @@ package tests import ( + "context" "fmt" - math_rand "math/rand" - "strings" - "sync" + "math/rand" "testing" "time" @@ -20,38 +19,35 @@ type TestSuite struct { logger log.Logger + ctx context.Context registries []registry.Registry - nodes []*registry.Node - services []*registry.Service + services []registry.ServiceNode - updateTime time.Duration - serviceOffset int + updateTime time.Duration } // CreateSuite creates the suite for test usage. -func CreateSuite(logger log.Logger, registries []registry.Registry, updateTime time.Duration, serviceOffset int) *TestSuite { +func CreateSuite(logger log.Logger, registries []registry.Registry, updateTime time.Duration) *TestSuite { r := &TestSuite{ - logger: logger, - registries: registries, - updateTime: updateTime, - serviceOffset: serviceOffset, + ctx: context.Background(), + logger: logger, + registries: registries, + updateTime: updateTime, } // Generate random ports to avoid conflicts - basePort1 := 10000 + math_rand.Intn(10000) //nolint:gosec - basePort2 := 20000 + math_rand.Intn(10000) //nolint:gosec + basePort1 := 10000 + rand.Intn(10000) //nolint:gosec + basePort2 := 20000 + rand.Intn(10000) //nolint:gosec - // Each node gets a unique port to avoid conflicts - r.nodes = append(r.nodes, ®istry.Node{ID: "node0-http", Address: fmt.Sprintf("10.0.0.10:%d", basePort1), Transport: "http"}) - r.nodes = append(r.nodes, ®istry.Node{ID: "node0-grpc", Address: fmt.Sprintf("10.0.0.10:%d", basePort1+1), Transport: "grpc"}) - r.nodes = append(r.nodes, ®istry.Node{ID: "node0-frpc", Address: fmt.Sprintf("10.0.0.10:%d", basePort1+2), Transport: "frpc"}) - r.nodes = append(r.nodes, ®istry.Node{ID: "node1-http", Address: fmt.Sprintf("10.0.0.11:%d", basePort2), Transport: "http"}) - r.nodes = append(r.nodes, ®istry.Node{ID: "node1-grpc", Address: fmt.Sprintf("10.0.0.11:%d", basePort2+1), Transport: "grpc"}) - r.nodes = append(r.nodes, ®istry.Node{ID: "node1-frpc", Address: fmt.Sprintf("10.0.0.11:%d", basePort2+2), Transport: "frpc"}) - - r.services = append(r.services, ®istry.Service{Name: "orb.test.svc.0", Version: "v1", Nodes: []*registry.Node{r.nodes[0]}}) - r.services = append(r.services, ®istry.Service{Name: "orb.test.svc.1", Version: "v1", Nodes: []*registry.Node{r.nodes[1]}}) - r.services = append(r.services, ®istry.Service{Name: "orb.test.svc.2", Version: "v1", Nodes: []*registry.Node{r.nodes[2]}}) + // All the test services. + r.services = []registry.ServiceNode{ + {Name: "orb.test.svc.0", Version: "v1", Address: fmt.Sprintf("10.0.0.10:%d", basePort1), Scheme: "http"}, + {Name: "orb.test.svc.1", Version: "v1", Address: fmt.Sprintf("10.0.0.10:%d", basePort1+1), Scheme: "grpc"}, + {Name: "orb.test.svc.2", Version: "v1", Address: fmt.Sprintf("10.0.0.10:%d", basePort1+2), Scheme: "frpc"}, + {Name: "orb.test.svc.3", Version: "v1", Address: fmt.Sprintf("10.0.0.11:%d", basePort2), Scheme: "http"}, + {Name: "orb.test.svc.4", Version: "v1", Address: fmt.Sprintf("10.0.0.11:%d", basePort2+1), Scheme: "grpc"}, + {Name: "orb.test.svc.5", Version: "v1", Address: fmt.Sprintf("10.0.0.11:%d", basePort2+2), Scheme: "frpc"}, + } return r } @@ -59,7 +55,7 @@ func CreateSuite(logger log.Logger, registries []registry.Registry, updateTime t // SetupSuite setups the test suite. func (r *TestSuite) SetupSuite() { for _, service := range r.services { - if err := r.registries[0].Register(service); err != nil { + if err := r.randomRegistry().Register(r.ctx, service); err != nil { r.logger.Error("Failed to register service", "error", err, "service", service.Name) } } @@ -68,114 +64,111 @@ func (r *TestSuite) SetupSuite() { // TearDownSuite runs after all tests. func (r *TestSuite) TearDownSuite() { for _, service := range r.services { - if err := r.registries[0].Deregister(service); err != nil { + if err := r.randomRegistry().Deregister(r.ctx, service); err != nil { r.logger.Error("Failed to deregister service", "error", err, "service", service.Name) } } } +func (r *TestSuite) randomRegistry() registry.Registry { + return r.registries[rand.Intn(len(r.registries))] //nolint:gosec +} + // TestRegister tests registering. func (r *TestSuite) TestRegister() { - service := registry.Service{Name: "orb.test.svc.3", Version: "v1.0.0", Nodes: []*registry.Node{r.nodes[3]}} - r.Require().NoError(r.registries[0].Register(&service)) + service := registry.ServiceNode{ + Name: "orb.test.svc.6", + Version: "v1.0.0", + Address: r.services[3].Address, + Scheme: r.services[3].Scheme, + } + r.Require().NoError(r.randomRegistry().Register(r.ctx, service)) time.Sleep(r.updateTime) defer func() { - err := r.registries[0].Deregister(&service) + err := r.randomRegistry().Deregister(r.ctx, service) if err != nil { - panic(err) + r.logger.Error("Failed to cleanup from TestRegister", "error", err) } }() for idx, reg := range r.registries { r.Run(fmt.Sprintf("reg-%d", idx), func() { - services, err := reg.ListServices() + services, err := reg.ListServices(r.ctx, "", "", nil) r.Require().NoError(err) - r.Require().Len(services, len(r.services)+1+r.serviceOffset) + r.Len(services, len(r.services)+1) - services, err = reg.GetService(service.Name) + services, err = reg.GetService(r.ctx, "", "", service.Name, nil) r.Require().NoError(err) - r.Require().Len(services, 1) + r.Len(services, 1) r.Equal(service.Version, services[0].Version) - r.Equal(service.Nodes[0].Transport, services[0].Nodes[0].Transport) + r.Equal(service.Scheme, services[0].Scheme) }) } } // TestGetAllNodesAndVersions tests that all nodes and all versions of a service are returned. // -//nolint:gocognit,funlen +//nolint:funlen func (r *TestSuite) TestGetAllNodesAndVersions() { // Use a unique service name for this test to avoid conflicts baseName := "orb.test.allnodes" // Create multiple services with different versions - services := []*registry.Service{ + services := []registry.ServiceNode{ // Service 1: v1.0.0 with two nodes { - Name: baseName + ".svc1", - Version: "v1.0.0", - Nodes: []*registry.Node{ - { - ID: "node-1-1", - Address: "10.0.1.1:8080", - Transport: "http", - Metadata: map[string]string{"region": "us-east"}, - }, - { - ID: "node-1-2", - Address: "10.0.1.2:8080", - Transport: "grpc", - Metadata: map[string]string{"region": "us-west"}, - }, - }, + Name: baseName + ".svc1", + Version: "v1.0.0", + Address: "10.0.1.1:8080", + Scheme: "http", + Metadata: map[string]string{"region": "us-east"}, + }, + { + Name: baseName + ".svc1", + Version: "v1.0.0", + Address: "10.0.1.2:8080", + Scheme: "grpc", + Metadata: map[string]string{"region": "us-west"}, }, // Service 1: v2.0.0 with one node { - Name: baseName + ".svc1", - Version: "v2.0.0", - Nodes: []*registry.Node{ - { - ID: "node-1-3", - Address: "10.0.1.3:8080", - Transport: "http", - Metadata: map[string]string{"region": "eu-west"}, - }, - }, + Name: baseName + ".svc1", + Version: "v2.0.0", + Address: "10.0.1.3:8080", + Scheme: "http", + Metadata: map[string]string{"region": "eu-west"}, }, // Service 2: v1.0.0 with three nodes with different transports { - Name: baseName + ".svc2", - Version: "v1.0.0", - Nodes: []*registry.Node{ - { - ID: "node-2-1", - Address: "10.0.2.1:8080", - Transport: "http", - Metadata: map[string]string{"region": "us-east"}, - }, - { - ID: "node-2-2", - Address: "10.0.2.2:8080", - Transport: "grpc", - Metadata: map[string]string{"region": "us-west"}, - }, - { - ID: "node-2-3", - Address: "10.0.2.3:8080", - Transport: "http3", - Metadata: map[string]string{"region": "eu-west"}, - }, - }, + Name: baseName + ".svc2", + Version: "v1.0.0", + Address: "10.0.2.1:8080", + Scheme: "http", + Metadata: map[string]string{"region": "us-east"}, + }, + { + Name: baseName + ".svc2", + Version: "v1.0.0", + Address: "10.0.2.2:8080", + Scheme: "grpc", + Metadata: map[string]string{"region": "us-west"}, + }, + { + Name: baseName + ".svc2", + Version: "v1.0.0", + Address: "10.0.2.3:8080", + Scheme: "http3", + Metadata: map[string]string{"region": "eu-west"}, }, } - for _, registry := range r.registries { - r.Run("registry-"+registry.String(), func() { + for _, reg := range r.registries { + r.Run("registry-"+reg.String(), func() { // Register all services for _, svc := range services { - r.Require().NoError(registry.Register(svc)) + r.Require().NoError(reg.Register(r.ctx, svc)) } time.Sleep(r.updateTime) @@ -183,162 +176,146 @@ func (r *TestSuite) TestGetAllNodesAndVersions() { // Cleanup when done defer func() { for _, svc := range services { - r.Require().NoError(registry.Deregister(svc)) + r.Require().NoError(reg.Deregister(r.ctx, svc)) } }() // Test 1: GetService should return all versions of service 1 service1Name := baseName + ".svc1" - service1Results, err := registry.GetService(service1Name) + service1Results, err := reg.GetService(r.ctx, "", "", service1Name, nil) r.Require().NoError(err) - // Verify that each version has the correct number of nodes - versionsFound := map[string]bool{ - "v1.0.0": false, - "v2.0.0": false, + // Group results by version to validate + resultsMap := make(map[string][]registry.ServiceNode) + for _, svc := range service1Results { + resultsMap[svc.Version] = append(resultsMap[svc.Version], svc) } - for _, svc := range service1Results { - versionsFound[svc.Version] = true - - if svc.Version == "v1.0.0" { - r.Require().Len(svc.Nodes, 2, "v1.0.0 should have 2 nodes") - r.Require().ElementsMatch( - []string{"node-1-1", "node-1-2"}, - []string{svc.Nodes[0].ID, svc.Nodes[1].ID}, - "Node IDs should match") - - // Verify transports are preserved - transports := map[string]bool{} - for _, node := range svc.Nodes { - transports[node.Transport] = true - } - - r.Require().Len(transports, 2, "Should have both http and grpc transports") - r.Require().True(transports["http"], "Should have http transport") - r.Require().True(transports["grpc"], "Should have grpc transport") - } else if svc.Version == "v2.0.0" { - r.Require().Len(svc.Nodes, 1, "v2.0.0 should have 1 node") - r.Equal("node-1-3", svc.Nodes[0].ID) - r.Equal("http", svc.Nodes[0].Transport, "Transport should be preserved") - } + // Verify we have both versions + r.Require().Contains(resultsMap, "v1.0.0", "v1.0.0 should be found") + r.Require().Contains(resultsMap, "v2.0.0", "v2.0.0 should be found") + + // Verify v1.0.0 has 2 nodes + r.Require().Len(resultsMap["v1.0.0"], 2, "v1.0.0 should have 2 nodes") + + // Verify v2.0.0 has 1 node + r.Require().Len(resultsMap["v2.0.0"], 1, "v2.0.0 should have 1 node") + + // Verify transports are preserved for v1.0.0 + schemes := map[string]bool{} + for _, node := range resultsMap["v1.0.0"] { + schemes[node.Scheme] = true } - r.Require().True(versionsFound["v1.0.0"], "v1.0.0 should be found") - r.Require().True(versionsFound["v2.0.0"], "v2.0.0 should be found") + r.Require().Len(schemes, 2, "Should have both http and grpc schemes") + r.Require().True(schemes["http"], "Should have http scheme") + r.Require().True(schemes["grpc"], "Should have grpc scheme") // Test 2: GetService should return all nodes for service 2 service2Name := baseName + ".svc2" - service2Results, err := registry.GetService(service2Name) + service2Results, err := reg.GetService(r.ctx, "", "", service2Name, nil) r.Require().NoError(err) - r.Require().Len(service2Results, 1, "Should return one version of service 2") - r.Require().Len(service2Results[0].Nodes, 3, "Service 2 should have 3 nodes") + r.Require().Len(service2Results, 3, "Service 2 should have 3 nodes") - // Verify all node IDs are present - nodeIDs := []string{} - for _, node := range service2Results[0].Nodes { - nodeIDs = append(nodeIDs, node.ID) + // Verify all schemes are present + schemeSet := map[string]bool{} + for _, node := range service2Results { + schemeSet[node.Scheme] = true } - r.Require().ElementsMatch( - []string{"node-2-1", "node-2-2", "node-2-3"}, - nodeIDs, - "All node IDs should be present") - - // Verify all transports are present - transportSet := map[string]bool{} - for _, node := range service2Results[0].Nodes { - transportSet[node.Transport] = true - } - - r.Require().Len(transportSet, 3, "All three transports should be present") - r.Require().True(transportSet["http"], "HTTP transport should be present") - r.Require().True(transportSet["grpc"], "gRPC transport should be present") - r.Require().True(transportSet["http3"], "HTTP/3 transport should be present") + r.Require().Len(schemeSet, 3, "All three schemes should be present") + r.Require().True(schemeSet["http"], "HTTP scheme should be present") + r.Require().True(schemeSet["grpc"], "gRPC scheme should be present") + r.Require().True(schemeSet["http3"], "HTTP/3 scheme should be present") // Test 3: ListServices should return all services - allServices, err := registry.ListServices() + allServices, err := reg.ListServices(r.ctx, "", "", nil) r.Require().NoError(err) // Count the number of instances of our test services service1Count := 0 service2Count := 0 - totalNodes := 0 for _, svc := range allServices { if svc.Name == service1Name { service1Count++ - totalNodes += len(svc.Nodes) } else if svc.Name == service2Name { service2Count++ - totalNodes += len(svc.Nodes) } } - r.Require().Equal(2, service1Count, "ListServices should return two versions of service 1") - r.Require().Equal(1, service2Count, "ListServices should return one version of service 2") - r.Require().Equal(6, totalNodes, "Total node count should be 6 (2+1+3)") + r.Require().Equal(3, service1Count, "ListServices should return all nodes of service 1") + r.Require().Equal(3, service2Count, "ListServices should return all nodes of service 2") }) } } // TestDeregister tests deregistering. func (r *TestSuite) TestDeregister() { - service1 := registry.Service{Name: "orb.test.svc.4", Version: "v1", Nodes: []*registry.Node{r.nodes[4]}} - service2 := registry.Service{Name: "orb.test.svc.4", Version: "v2", Nodes: []*registry.Node{r.nodes[5]}} + service1 := registry.ServiceNode{ + Name: "orb.test.deregister", + Version: "v1", + Address: r.services[4].Address, + Scheme: r.services[4].Scheme, + } + service2 := registry.ServiceNode{ + Name: "orb.test.deregister", + Version: "v2", + Address: r.services[5].Address, + Scheme: r.services[5].Scheme, + } - r.Require().NoError(r.registries[0].Register(&service1)) + r.Require().NoError(r.randomRegistry().Register(r.ctx, service1)) time.Sleep(r.updateTime) - services, err := r.registries[0].ListServices() + services, err := r.randomRegistry().ListServices(r.ctx, "", "", nil) r.Require().NoError(err) - r.Require().Len(services, len(r.services)+1+r.serviceOffset) + r.Len(services, len(r.services)+1) - services, err = r.registries[0].GetService(service1.Name) + services, err = r.randomRegistry().GetService(r.ctx, "", "", service1.Name, nil) r.Require().NoError(err) - r.Require().Len(services, 1) - r.Require().Equal(service1.Version, services[0].Version) + r.Len(services, 1) + r.Equal(service1.Version, services[0].Version) - r.Require().NoError(r.registries[0].Register(&service2)) + r.Require().NoError(r.randomRegistry().Register(r.ctx, service2)) time.Sleep(r.updateTime) - services, err = r.registries[0].GetService(service2.Name) + services, err = r.randomRegistry().GetService(r.ctx, "", "", service2.Name, nil) r.Require().NoError(err) - r.Require().Len(services, 2) + r.Len(services, 2) - r.Require().NoError(r.registries[0].Deregister(&service1)) + r.Require().NoError(r.randomRegistry().Deregister(r.ctx, service1)) time.Sleep(r.updateTime) - services, err = r.registries[0].GetService(service1.Name) + services, err = r.randomRegistry().GetService(r.ctx, "", "", service1.Name, nil) r.Require().NoError(err) - r.Require().Len(services, 1) + r.Len(services, 1) - r.Require().NoError(r.registries[0].Deregister(&service2)) + r.Require().NoError(r.randomRegistry().Deregister(r.ctx, service2)) time.Sleep(r.updateTime) - services, err = r.registries[0].GetService(service1.Name) - r.Require().ErrorIs(registry.ErrNotFound, err) - r.Require().Empty(services) + services, err = r.randomRegistry().GetService(r.ctx, "", "", service1.Name, nil) + r.Require().ErrorIs(err, registry.ErrNotFound) + r.Empty(services) } // TestGetServiceAllRegistries tests a service on all registries. func (r *TestSuite) TestGetServiceAllRegistries() { for idx, reg := range r.registries { r.Run(fmt.Sprintf("reg-%d", idx), func() { - services, err := reg.GetService(r.services[0].Name) + services, err := reg.GetService(r.ctx, "", "", r.services[0].Name, nil) r.Require().NoError(err) - r.Require().Len(services, 1) - r.Require().Equal(r.services[0].Name, services[0].Name) - r.Require().Equal(len(r.services[0].Nodes), len(services[0].Nodes)) + r.Len(services, 1) + r.Equal(r.services[0].Name, services[0].Name) }) } } // TestGetServiceWithNoNodes tests a non existent service. func (r *TestSuite) TestGetServiceWithNoNodes() { - services, err := r.registries[math_rand.Intn(len(r.registries))].GetService("missing") //nolint:gosec - r.Require().ErrorIs(registry.ErrNotFound, err) - r.Require().Empty(services) + services, err := r.randomRegistry().GetService(r.ctx, "", "", "missing", nil) + r.Require().ErrorIs(err, registry.ErrNotFound) + r.Empty(services) } // BenchmarkGetService benchmarks. @@ -350,14 +327,13 @@ func (r *TestSuite) BenchmarkGetService(b *testing.B) { b.ResetTimer() - for n := 0; n < b.N; n++ { //nolint:dupl - id := math_rand.Intn(len(r.services)) //nolint:gosec + for n := 0; n < b.N; n++ { + id := rand.Intn(len(r.services)) //nolint:gosec - services, err := r.registries[math_rand.Intn(len(r.registries))].GetService(r.services[id].Name) //nolint:gosec + services, err := r.randomRegistry().GetService(r.ctx, "", "", r.services[id].Name, nil) r.Require().NoError(err) - r.Require().Len(services, 1) - r.Require().Equal(r.services[id].Name, services[0].Name) - r.Require().Equal(len(r.services[id].Nodes), len(services[0].Nodes)) + r.Len(services, 1) + r.Equal(r.services[id].Name, services[0].Name) } b.StopTimer() @@ -374,9 +350,9 @@ func (r *TestSuite) BenchmarkGetServiceWithNoNodes(b *testing.B) { b.ResetTimer() for n := 0; n < b.N; n++ { - services, err := r.registries[0].GetService("missing") - r.Require().ErrorIs(registry.ErrNotFound, err) - r.Require().Empty(services) + services, err := r.randomRegistry().GetService(r.ctx, "", "", "missing", nil) + r.Require().ErrorIs(err, registry.ErrNotFound) + r.Empty(services) } b.StopTimer() @@ -393,14 +369,13 @@ func (r *TestSuite) BenchmarkParallelGetService(b *testing.B) { b.ResetTimer() b.RunParallel(func(pb *testing.PB) { - for pb.Next() { //nolint:dupl - id := math_rand.Intn(len(r.services)) //nolint:gosec + for pb.Next() { + id := rand.Intn(len(r.services)) //nolint:gosec - services, err := r.registries[math_rand.Intn(len(r.registries))].GetService(r.services[id].Name) //nolint:gosec + services, err := r.randomRegistry().GetService(r.ctx, "", "", r.services[id].Name, nil) r.Require().NoError(err) - r.Require().Len(services, 1) - r.Require().Equal(r.services[id].Name, services[0].Name) - r.Require().Equal(len(r.services[id].Nodes), len(services[0].Nodes)) + r.Len(services, 1) + r.Equal(r.services[id].Name, services[0].Name) } }) @@ -410,55 +385,45 @@ func (r *TestSuite) BenchmarkParallelGetService(b *testing.B) { // TestWatchServices tests the watcher functionality. func (r *TestSuite) TestWatchServices() { - // Skip the test if we have no registries - if len(r.registries) == 0 { - r.T().Skip("No registries available for testing") - return - } - // Create a test service with a unique name for watching serviceName := "orb.test.watch" + time.Now().Format("20060102150405") - service := registry.Service{Name: serviceName, Version: "v1.0.0", Nodes: []*registry.Node{r.nodes[3]}} + service := registry.ServiceNode{ + Name: serviceName, + Version: "v1.0.0", + Address: r.services[3].Address, + Scheme: r.services[3].Scheme, + } // Register the service first to ensure it exists - err := r.registries[0].Register(&service) + err := r.randomRegistry().Register(r.ctx, service) r.Require().NoError(err) time.Sleep(r.updateTime) // Create a watcher - watcher, err := r.registries[0].Watch() + watcher, err := r.randomRegistry().Watch(r.ctx, registry.WatchService(serviceName)) r.Require().NoError(err) - r.Require().NotNil(watcher) - - //nolint:errcheck - defer watcher.Stop() + r.NotNil(watcher) // Update the service to trigger a watch event - service.Nodes = append(service.Nodes, r.nodes[2]) // Add another node + service.Metadata = map[string]string{"updated": "true"} // Modify metadata to trigger update // Start a goroutine to listen for events eventReceived := make(chan bool) go func() { - // Handle multiple events until we get one for our service - for i := 0; i < 20; i++ { // Try multiple times - result, err := watcher.Next() - if err != nil { - break - } - - if result != nil && result.Service != nil && result.Service.Name == serviceName { - eventReceived <- true - break - } + result, err := watcher.Next() + if err != nil { + return + } - // Check next event after a short delay - time.Sleep(50 * time.Millisecond) + if result != nil && result.Node.Name == serviceName { + eventReceived <- true + return } }() // Update the service that should trigger the watcher - err = r.registries[0].Register(&service) + err = r.randomRegistry().Register(r.ctx, service) r.Require().NoError(err) // Wait for the event with a timeout @@ -471,59 +436,67 @@ func (r *TestSuite) TestWatchServices() { } // Cleanup - err = r.registries[0].Deregister(&service) + err = r.randomRegistry().Deregister(r.ctx, service) r.Require().NoError(err) } // TestServiceUpdate tests updating an existing service. func (r *TestSuite) TestServiceUpdate() { + if r.registries[0].String() == "mdns" { + r.T().Skip("Skipping test for mdns registry") + return + } + // Initial service - service := registry.Service{ + service := registry.ServiceNode{ Name: "orb.test.update", Version: "v1.0.0", - Nodes: []*registry.Node{r.nodes[0]}, + Address: r.services[0].Address, + Scheme: r.services[0].Scheme, } // Register the service - r.Require().NoError(r.registries[0].Register(&service)) + r.Require().NoError(r.randomRegistry().Register(r.ctx, service)) time.Sleep(r.updateTime) // Verify initial service - services, err := r.registries[0].GetService(service.Name) + services, err := r.randomRegistry().GetService(r.ctx, "", "", service.Name, nil) r.Require().NoError(err) - r.Require().Len(services, 1) - r.Require().Len(services[0].Nodes, 1) + r.Len(services, 1) - // Update the service by adding a node - updatedService := registry.Service{ - Name: "orb.test.update", - Version: "v1.0.0", - Nodes: []*registry.Node{r.nodes[0], r.nodes[1]}, + // Update the service by adding metadata + updatedService := registry.ServiceNode{ + Name: "orb.test.update", + Version: "v1.0.0", + Address: r.services[0].Address, + Scheme: r.services[0].Scheme, + Metadata: map[string]string{"updated": "true"}, } // Register the updated service - r.Require().NoError(r.registries[0].Register(&updatedService)) + r.Require().NoError(r.randomRegistry().Register(r.ctx, updatedService)) time.Sleep(r.updateTime) // Verify the service was updated - services, err = r.registries[0].GetService(service.Name) + services, err = r.randomRegistry().GetService(r.ctx, "", "", service.Name, nil) r.Require().NoError(err) - r.Require().Len(services, 1) + r.Len(services, 1) - // Should now have 2 nodes - r.Require().Len(services[0].Nodes, 2) + // Should have metadata updated + r.Equal("true", services[0].Metadata["updated"]) // Cleanup - r.Require().NoError(r.registries[0].Deregister(&updatedService)) + r.Require().NoError(r.randomRegistry().Deregister(r.ctx, updatedService)) } // TestServiceMetadata tests handling of service metadata. func (r *TestSuite) TestServiceMetadata() { // Service with metadata - service := registry.Service{ + service := registry.ServiceNode{ Name: "orb.test.metadata", Version: "v1.0.0", - Nodes: []*registry.Node{r.nodes[0]}, + Address: r.services[0].Address, + Scheme: r.services[0].Scheme, Metadata: map[string]string{ "region": "us-west", "env": "test", @@ -532,39 +505,48 @@ func (r *TestSuite) TestServiceMetadata() { } // Register the service - r.Require().NoError(r.registries[0].Register(&service)) + r.Require().NoError(r.randomRegistry().Register(r.ctx, service)) time.Sleep(r.updateTime) // Verify the service can be retrieved with metadata intact - services, err := r.registries[0].GetService(service.Name) + services, err := r.randomRegistry().GetService(r.ctx, "", "", service.Name, nil) r.Require().NoError(err) - r.Require().Len(services, 1) + r.Len(services, 1) // Verify metadata was preserved - r.Require().Equal(service.Metadata["region"], services[0].Metadata["region"]) - r.Require().Equal(service.Metadata["env"], services[0].Metadata["env"]) - r.Require().Equal(service.Metadata["secure"], services[0].Metadata["secure"]) + r.Equal(service.Metadata["region"], services[0].Metadata["region"]) + r.Equal(service.Metadata["env"], services[0].Metadata["env"]) + r.Equal(service.Metadata["secure"], services[0].Metadata["secure"]) // Cleanup - r.Require().NoError(r.registries[0].Deregister(&service)) + r.Require().NoError(r.randomRegistry().Deregister(r.ctx, service)) } // TestMultipleVersions tests registering and retrieving services with multiple versions. func (r *TestSuite) TestMultipleVersions() { // Create services with same name but different versions - serviceV1 := registry.Service{Name: "orb.test.versions", Version: "v1.0.0", Nodes: []*registry.Node{r.nodes[0]}} - serviceV2 := registry.Service{Name: "orb.test.versions", Version: "v2.0.0", Nodes: []*registry.Node{r.nodes[1]}} + serviceV1 := registry.ServiceNode{ + Name: "orb.test.versions", + Version: "v1.0.0", + Address: r.services[0].Address, + Scheme: r.services[0].Scheme, + } + serviceV2 := registry.ServiceNode{ + Name: "orb.test.versions", + Version: "v2.0.0", + Address: r.services[1].Address, + Scheme: r.services[1].Scheme, + } // Register both versions - r.Require().NoError(r.registries[0].Register(&serviceV1)) - r.Require().NoError(r.registries[0].Register(&serviceV2)) + r.Require().NoError(r.randomRegistry().Register(r.ctx, serviceV1)) + r.Require().NoError(r.randomRegistry().Register(r.ctx, serviceV2)) time.Sleep(r.updateTime) // Get all versions of the service - services, err := r.registries[0].GetService(serviceV1.Name) - r.logger.Debug("GetService", "service", serviceV1.Name, "services", services) + services, err := r.randomRegistry().GetService(r.ctx, "", "", serviceV1.Name, nil) r.Require().NoError(err) - r.Require().Len(services, 2, "Should have found both versions of the service") + r.Require().GreaterOrEqual(len(services), 2, "Should have found both versions of the service") // Verify both versions are returned versions := map[string]bool{} @@ -576,8 +558,8 @@ func (r *TestSuite) TestMultipleVersions() { r.Require().True(versions["v2.0.0"], "v2.0.0 should be in the results") // Cleanup - r.Require().NoError(r.registries[0].Deregister(&serviceV1)) - r.Require().NoError(r.registries[0].Deregister(&serviceV2)) + r.Require().NoError(r.randomRegistry().Deregister(r.ctx, serviceV1)) + r.Require().NoError(r.randomRegistry().Deregister(r.ctx, serviceV2)) } // BenchmarkListServices benchmarks the performance of listing services. @@ -590,7 +572,7 @@ func (r *TestSuite) BenchmarkListServices(b *testing.B) { b.ResetTimer() for n := 0; n < b.N; n++ { - services, err := r.registries[math_rand.Intn(len(r.registries))].ListServices() //nolint:gosec + services, err := r.randomRegistry().ListServices(r.ctx, "", "", nil) r.Require().NoError(err) r.Require().NotEmpty(services) } @@ -599,294 +581,89 @@ func (r *TestSuite) BenchmarkListServices(b *testing.B) { r.TearDownSuite() } -// TestServiceWithEndpoints tests registering and retrieving services with endpoints. -func (r *TestSuite) TestServiceWithEndpoints() { - // Create a service with endpoints - endpoints := []*registry.Endpoint{ +// TestFiltering tests using options to filter services. +func (r *TestSuite) TestFiltering() { + // Create services with different attributes + services := []registry.ServiceNode{ { - Name: "method1", - Request: ®istry.Value{ - Name: "request1", - Type: "json", - }, - Response: ®istry.Value{ - Name: "response1", - Type: "json", - }, - Metadata: map[string]string{ - "endpoint_type": "rest", - "handler": "handler1", - }, + Name: "orb.test.filter", + Version: "v1.0.0", + Address: "10.0.1.1:8080", + Scheme: "http", + Namespace: "default", + Region: "us-west", }, { - Name: "method2", - Request: ®istry.Value{ - Name: "request2", - Type: "protobuf", - }, - Response: ®istry.Value{ - Name: "response2", - Type: "protobuf", - }, - Metadata: map[string]string{ - "endpoint_type": "grpc", - "handler": "handler2", - }, + Name: "orb.test.filter", + Version: "v2.0.0", + Address: "10.0.1.2:8080", + Scheme: "grpc", + Namespace: "default", + Region: "us-east", }, - } - - service := registry.Service{ - Name: "orb.test.endpoints", - Version: "v1.0.0", - Nodes: []*registry.Node{r.nodes[0]}, - Endpoints: endpoints, - } - - // Register the service - r.Require().NoError(r.registries[0].Register(&service)) - time.Sleep(r.updateTime) - - // Verify the service can be retrieved with endpoints intact - services, err := r.registries[0].GetService(service.Name) - r.Require().NoError(err) - r.Require().Len(services, 1) - - // Verify endpoints were preserved - r.Require().Len(services[0].Endpoints, len(endpoints)) - - for i, ep := range services[0].Endpoints { - r.Require().Equal(endpoints[i].Name, ep.Name) - - // Check request/response types - r.Require().Equal(endpoints[i].Request.Name, ep.Request.Name) - r.Require().Equal(endpoints[i].Request.Type, ep.Request.Type) - r.Require().Equal(endpoints[i].Response.Name, ep.Response.Name) - r.Require().Equal(endpoints[i].Response.Type, ep.Response.Type) - - // Check metadata - r.Require().Equal(endpoints[i].Metadata["endpoint_type"], ep.Metadata["endpoint_type"]) - r.Require().Equal(endpoints[i].Metadata["handler"], ep.Metadata["handler"]) - } - - // Cleanup - r.Require().NoError(r.registries[0].Deregister(&service)) -} - -// TestConcurrentRegistrations tests concurrent registration and deregistration operations. -func (r *TestSuite) TestConcurrentRegistrations() { - const numServices = 10 - - const numWorkers = 3 - - services := make([]*registry.Service, numServices) - for i := 0; i < numServices; i++ { - services[i] = ®istry.Service{ - Name: fmt.Sprintf("orb.test.concurrent.%d", i), - Version: "v1.0.0", - Nodes: []*registry.Node{r.nodes[i%len(r.nodes)]}, - } - } - - // Create a wait group to synchronize goroutines - wg := sync.WaitGroup{} - // Start multiple workers to register services concurrently - for workerID := 0; workerID < numWorkers; workerID++ { - wg.Add(1) - - go func(workerId int) { - defer wg.Done() - - // Each worker operates on a subset of services - start := (workerId * numServices) / numWorkers - end := ((workerId + 1) * numServices) / numWorkers - - for i := start; i < end; i++ { - // Register the service - err := r.registries[0].Register(services[i]) - - r.NoError(err) - } - - // Small delay to allow updates to propagate - time.Sleep(r.updateTime) - - // Verify the services were registered - for i := start; i < end; i++ { - result, err := r.registries[0].GetService(services[i].Name) - - r.NoError(err, "Failed to get service: %s", services[i].Name) - r.Len(result, 1) - - if len(result) >= len(services) { - r.Equal(services[i].Name, result[0].Name) - } - } - - // Now deregister the services - for i := start; i < end; i++ { - err := r.registries[0].Deregister(services[i]) - - r.NoError(err) - } - }(workerID) - } - - // Wait for all workers to complete - wg.Wait() - - // Verify all services were successfully deregistered - time.Sleep(r.updateTime) - - for i := 0; i < numServices; i++ { - r.logger.Debug("checking", "name", services[i].Name) - n, err := r.registries[0].GetService(services[i].Name) - r.Require().Empty(n) - r.Require().ErrorIs(err, registry.ErrNotFound) - } -} - -// TestMetadataFiltering tests using custom logic to filter services by metadata. -func (r *TestSuite) TestMetadataFiltering() { - // Create services with different environments in metadata - servicesProd := []*registry.Service{ { - Name: "orb.test.filter.1", - Version: "v1.0.0", - Nodes: []*registry.Node{r.nodes[0]}, - Metadata: map[string]string{ - "env": "production", - "region": "us-west", - }, - }, - { - Name: "orb.test.filter.2", - Version: "v1.0.0", - Nodes: []*registry.Node{r.nodes[1]}, - Metadata: map[string]string{ - "env": "production", - "region": "us-east", - }, - }, - } - - servicesStaging := []*registry.Service{ - { - Name: "orb.test.filter.3", - Version: "v1.0.0", - Nodes: []*registry.Node{r.nodes[2]}, - Metadata: map[string]string{ - "env": "staging", - "region": "eu-west", - }, + Name: "orb.test.filter", + Version: "v1.0.0", + Address: "10.0.1.3:8080", + Scheme: "https", + Namespace: "production", + Region: "eu-west", }, } // Register all services - for _, svc := range append(servicesProd, servicesStaging...) { - r.Require().NoError(r.registries[0].Register(svc)) + for _, svc := range services { + r.Require().NoError(r.randomRegistry().Register(r.ctx, svc)) } - time.Sleep(r.updateTime) - - // Get all services - allServices, err := r.registries[0].ListServices() - r.Require().NoError(err) - - // Manually filter for production services - prodServices := []*registry.Service{} - - for _, svc := range allServices { - // Skip non-test services (those not starting with orb.test.filter) - if !strings.HasPrefix(svc.Name, "orb.test.filter") { - continue - } - - // Only include services with env=production metadata - if env, ok := svc.Metadata["env"]; ok && env == "production" { - prodServices = append(prodServices, svc) - } - } - - // Verify we filtered correctly - r.Require().Len(prodServices, len(servicesProd), "Should find only the production services") - // Cleanup - for _, svc := range append(servicesProd, servicesStaging...) { - r.Require().NoError(r.registries[0].Deregister(svc)) - } -} - -// TestServiceNodesHealth simulates checking node health in a registry. -func (r *TestSuite) TestServiceNodesHealth() { - // Create a service with multiple nodes - nodes := []*registry.Node{ - { - ID: "healthy-node-1", - Address: "10.0.0.1:8080", - Metadata: map[string]string{"status": "healthy"}, - Transport: "http", - }, - { - ID: "healthy-node-2", - Address: "10.0.0.2:8080", - Metadata: map[string]string{"status": "healthy"}, - Transport: "http", - }, - } - - service := registry.Service{ - Name: "orb.test.health", - Version: "v1.0.0", - Nodes: nodes, - } + defer func() { + for _, svc := range services { + r.Require().NoError(r.randomRegistry().Deregister(r.ctx, svc)) + } + }() - // Register the service - r.Require().NoError(r.registries[0].Register(&service)) time.Sleep(r.updateTime) - // Retrieve the service - services, err := r.registries[0].GetService(service.Name) + // Test filtering by version and other parameters + filtered, err := r.randomRegistry().GetService( + r.ctx, "default", "us-west", "orb.test.filter", []string{"http"}) r.Require().NoError(err) - r.Require().Len(services, 1) - r.Require().Len(services[0].Nodes, 2) - - // Simulate a node becoming unhealthy by updating its metadata - nodes[0].Metadata["status"] = "unhealthy" - - // Update the service with the modified node - updatedService := registry.Service{ - Name: service.Name, - Version: service.Version, - Nodes: []*registry.Node{nodes[0]}, - } - r.Require().NoError(r.registries[0].Register(&updatedService)) - time.Sleep(r.updateTime) - - // Retrieve the service again - services, err = r.registries[0].GetService(service.Name) + r.Require().Len(filtered, 1, "Should find exactly one service with version v1.0.0 in default/us-west") + r.Require().Equal("v1.0.0", filtered[0].Version) + r.Require().Equal("default", filtered[0].Namespace) + r.Require().Equal("us-west", filtered[0].Region) + + // Test filtering by namespace + filtered, err = r.randomRegistry().GetService( + r.ctx, "production", "eu-west", "orb.test.filter", nil) r.Require().NoError(err) - r.Require().Len(services, 1) - r.Require().Len(services[0].Nodes, 2) - - // Verify that one node is now marked as unhealthy - healthyNodes := 0 - unhealthyNodes := 0 - - for _, node := range services[0].Nodes { - if status, ok := node.Metadata["status"]; ok { - if status == "healthy" { - healthyNodes++ - } else if status == "unhealthy" { - unhealthyNodes++ - } - } - } - - r.Require().Equal(1, healthyNodes, "Should have one healthy node") - r.Require().Equal(1, unhealthyNodes, "Should have one unhealthy node") - - // Cleanup - r.Require().NoError(r.registries[0].Deregister(&service)) + r.Require().Len(filtered, 1, "Should find exactly one service in production/eu-west") + r.Require().Equal("v1.0.0", filtered[0].Version) + r.Require().Equal("production", filtered[0].Namespace) + r.Require().Equal("eu-west", filtered[0].Region) + + // Test filtering by region + filtered, err = r.randomRegistry().GetService( + r.ctx, "default", "us-east", "orb.test.filter", nil) + r.Require().NoError(err) + r.Require().Len(filtered, 1, "Should find exactly one service in default/us-east") + r.Require().Equal("v2.0.0", filtered[0].Version) + r.Require().Equal("default", filtered[0].Namespace) + r.Require().Equal("us-east", filtered[0].Region) + + // Test filtering by scheme + filtered, err = r.randomRegistry().GetService( + r.ctx, "default", "us-west", "orb.test.filter", []string{"http"}) + r.Require().NoError(err) + r.Require().Len(filtered, 1, "Should find exactly one service with HTTP scheme") + r.Require().Equal("http", filtered[0].Scheme) + + // Test for no matches with a combination of filters + filtered, err = r.randomRegistry().GetService( + r.ctx, "production", "us-east", "orb.test.filter", nil) + r.Require().ErrorIs(err, registry.ErrNotFound) + r.Require().Empty(filtered, "Should find no services in production/us-east") } // BenchmarkRegisterDeregister benchmarks the performance of registering and deregistering services. @@ -896,21 +673,22 @@ func (r *TestSuite) BenchmarkRegisterDeregister(b *testing.B) { r.SetT(&testing.T{}) // Create a service just for this benchmark - service := ®istry.Service{ + service := registry.ServiceNode{ Name: "orb.test.benchmark.regdereg", Version: "v1.0.0", - Nodes: []*registry.Node{r.nodes[0]}, + Address: r.services[0].Address, + Scheme: r.services[0].Scheme, } b.ResetTimer() for n := 0; n < b.N; n++ { // Register - err := r.registries[0].Register(service) + err := r.randomRegistry().Register(r.ctx, service) r.Require().NoError(err) // Deregister - err = r.registries[0].Deregister(service) + err = r.randomRegistry().Deregister(r.ctx, service) r.Require().NoError(err) } } diff --git a/scripts/deps.sh b/scripts/deps.sh index 070816d9..6d3c164a 100755 --- a/scripts/deps.sh +++ b/scripts/deps.sh @@ -1,13 +1,13 @@ #!/bin/bash ###################################################################################### -# Release a plugin # +# Update plugin dependencies # # # # Usage: # -# $ release.sh all # -# $ release.sh server/http # -# $ release.sh server/http,server/grpc # -# $ release.sh server/* # +# $ deps.sh main all # +# $ deps.sh main server/http # +# $ deps.sh main server/http,server/grpc # +# $ deps.sh main server/* # # # ###################################################################################### @@ -50,17 +50,18 @@ function check_if_changed() { } function update_deps() { - local pkg="$1" + local branch="$1" + local pkg="$2" pushd "${pkg}" >/dev/null || exit go mod tidy || true - go get -u github.com/go-orb/go-orb@main + go get -u github.com/go-orb/go-orb@${branch} for m in $(grep github.com/go-orb/plugins/ go.mod | grep -E -v "^module" | awk '{ print $1 }'); do - if ! go get -u "${m}@main"; then + if ! go get -u "${m}@${branch}"; then # try another time sleep 5 - go get -u "${m}@main" - if ! go get -u "${m}@main"; then + go get -u "${m}@${branch}" + if ! go get -u "${m}@${branch}"; then echo "updated_deps: Failed to update dependency ${m}" exit 1 fi @@ -86,12 +87,13 @@ function update_deps() { } function upgrade() { - if [[ ! -f "${1}/go.mod" ]]; then - echo "Unknown package '${1}' given." + if [[ ! -f "${2}/go.mod" ]]; then + echo "Unknown package '${2}' given." return 1 fi - local pkg="${1}" + local branch="${1}" + local pkg="${2}" echo "Checking ${pkg}" if check_if_changed "${pkg}"; then @@ -99,27 +101,31 @@ function upgrade() { fi echo "Update deps for ${pkg}" - update_deps "${pkg}" + update_deps "${branch}" "${pkg}" } function upgrade_all() { - find . -name 'go.mod' -print0 | xargs -0 -n 1 -P 0 ${SCRIPT_DIR}/deps.sh + find . -name 'go.mod' -print0 | xargs -0 -n 1 -P 0 ${SCRIPT_DIR}/deps.sh "${1}" } function upgrade_specific() { + local branch="${1}" + while read -r pkg; do if [[ "${pkg}" == "./.github/go.mod" ]]; then continue fi - update_deps "${pkg%go.mod}" "0" - done < <(echo "${1}" | tr "," "\n") + echo update_deps "${branch}" "${pkg%go.mod}" + update_deps "${branch}" "${pkg%go.mod}" + done < <(echo "${2}" | tr "," "\n") } -case $1 in +case $2 in "all") - upgrade_all + upgrade_all "${1}" ;; *) - upgrade_specific "${1}" + upgrade_specific "${1}" "${2}" + ;; esac \ No newline at end of file diff --git a/server/drpc/drpc.go b/server/drpc/drpc.go index 5eba7ba2..173c0707 100644 --- a/server/drpc/drpc.go +++ b/server/drpc/drpc.go @@ -15,7 +15,6 @@ import ( "github.com/go-orb/go-orb/log" "github.com/go-orb/go-orb/registry" orbserver "github.com/go-orb/go-orb/server" - "github.com/go-orb/go-orb/types" "github.com/go-orb/go-orb/util/addr" ) @@ -26,6 +25,9 @@ const Plugin = "drpc" // Server is the drpc Server for go-orb. type Server struct { + serviceName string + serviceVersion string + config *Config logger log.Logger registry registry.Type @@ -90,11 +92,11 @@ func (s *Server) Start(ctx context.Context) error { s.started = true - return s.registryRegister() + return s.registryRegister(ctx) } // Stop will stop the dRPC server. -func (s *Server) Stop(_ context.Context) error { +func (s *Server) Stop(ctx context.Context) error { if !s.started { return nil } @@ -102,7 +104,7 @@ func (s *Server) Stop(_ context.Context) error { // Stops the dRPC Server. s.cancelFunc() - return s.registryDeregister() + return s.registryDeregister(ctx) } // AddHandler adds a handler for later registration. @@ -139,11 +141,6 @@ func (s *Server) Transport() string { return "drpc" } -// EntrypointID returns the id of this entrypoint (node) in the registry. -func (s *Server) EntrypointID() string { - return s.registry.ServiceName() + types.DefaultSeparator + s.config.Name -} - // String returns the entrypoint type. func (s *Server) String() string { return Plugin @@ -169,52 +166,29 @@ func (s *Server) Router() *Mux { return s.mux } -func (s *Server) getEndpoints() []*registry.Endpoint { - result := make([]*registry.Endpoint, 0, len(s.endpoints)) - - for _, r := range s.endpoints { - s.logger.Trace("found endpoint", "name", r[1:]) - - result = append(result, ®istry.Endpoint{ - Name: r, - Metadata: map[string]string{"stream": "true"}, - }) +func (s *Server) registryService() registry.ServiceNode { + return registry.ServiceNode{ + Name: s.serviceName, + Version: s.serviceVersion, + Address: s.Address(), + Scheme: s.Transport(), + Metadata: make(map[string]string), } - - return result } -func (s *Server) registryService() *registry.Service { - node := ®istry.Node{ - ID: s.EntrypointID(), - Address: s.Address(), - Transport: s.Transport(), - Metadata: make(map[string]string), - } - - return ®istry.Service{ - Name: s.registry.ServiceName(), - Version: s.registry.ServiceVersion(), - Nodes: []*registry.Node{node}, - Endpoints: s.getEndpoints(), - } -} - -func (s *Server) registryRegister() error { - rService := s.registryService() - - return s.registry.Register(rService) +func (s *Server) registryRegister(ctx context.Context) error { + return s.registry.Register(ctx, s.registryService()) } -func (s *Server) registryDeregister() error { - rService := s.registryService() - - return s.registry.Deregister(rService) +func (s *Server) registryDeregister(ctx context.Context) error { + return s.registry.Deregister(ctx, s.registryService()) } // Provide creates a new entrypoint for a single address. You can create // multiple entrypoints for multiple addresses and ports. func Provide( + name string, + version string, configData map[string]any, logger log.Logger, reg registry.Type, @@ -251,11 +225,11 @@ func Provide( cfg.OptHandlers = append(cfg.OptHandlers, h) } - return New(cfg, logger, reg) + return New(name, version, cfg, logger, reg) } // New creates a dRPC Server from a Config struct. -func New(acfg any, logger log.Logger, reg registry.Type) (orbserver.Entrypoint, error) { +func New(name string, version string, acfg any, logger log.Logger, reg registry.Type) (orbserver.Entrypoint, error) { cfg, ok := acfg.(*Config) if !ok { return nil, fmt.Errorf("drpc invalid config: %v", cfg) @@ -277,13 +251,15 @@ func New(acfg any, logger log.Logger, reg registry.Type) (orbserver.Entrypoint, ctx, cancelFunc := context.WithCancel(context.Background()) entrypoint := Server{ - config: cfg, - logger: logger, - registry: reg, - handlers: cfg.OptHandlers, - middlewares: cfg.OptMiddlewares, - ctx: ctx, - cancelFunc: cancelFunc, + serviceName: name, + serviceVersion: version, + config: cfg, + logger: logger, + registry: reg, + handlers: cfg.OptHandlers, + middlewares: cfg.OptMiddlewares, + ctx: ctx, + cancelFunc: cancelFunc, } return &entrypoint, nil diff --git a/server/drpc/go.mod b/server/drpc/go.mod index 733e8520..528d8fe3 100644 --- a/server/drpc/go.mod +++ b/server/drpc/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/server/drpc go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 github.com/zeebo/errs v1.4.0 google.golang.org/protobuf v1.36.5 storj.io/drpc v0.0.34 diff --git a/server/drpc/go.sum b/server/drpc/go.sum index 07da6194..d2a3a57c 100644 --- a/server/drpc/go.sum +++ b/server/drpc/go.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= diff --git a/server/grpc/go.mod b/server/grpc/go.mod index 75fcb8a8..da77dc65 100644 --- a/server/grpc/go.mod +++ b/server/grpc/go.mod @@ -3,12 +3,12 @@ module github.com/go-orb/plugins/server/grpc go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3 - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/config/source/file v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/config/source/file v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65 github.com/stretchr/testify v1.10.0 google.golang.org/grpc v1.71.0 google.golang.org/protobuf v1.36.5 @@ -18,9 +18,11 @@ require ( dario.cat/mergo v1.0.1 // indirect github.com/cornelk/hashmap v1.0.8 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/lithammer/shortuuid/v3 v3.0.7 // indirect github.com/miekg/dns v1.1.64 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect golang.org/x/mod v0.24.0 // indirect diff --git a/server/grpc/go.sum b/server/grpc/go.sum index dda0ac2c..e601de95 100644 --- a/server/grpc/go.sum +++ b/server/grpc/go.sum @@ -8,24 +8,27 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3 h1:aK9T/j8iHppOp8DBUKW32s8/iz4rQm3OKgqM1tT8JVk= -github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3/go.mod h1:A/CzKW0isS1OnxIvMYFJNR+kiEy519aP0o/ptr26HHo= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 h1:auojRTYubvH+2JRLgE9I0O8nUrhT2e6sZpKv+IyoQ7U= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:RQ43qp8cY/yyfZ/rukmMVywaEb3IuC50Eq92qekmnUk= -github.com/go-orb/plugins/config/source/file v0.1.1-0.20250320235901-3af29c3a3b34 h1:KuPHiH1lkxdy4pzbXRjtBgf9X8S0l8eSaCPO5WMj/VE= -github.com/go-orb/plugins/config/source/file v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:4P+GclfUx1+m1Zur9EXKMXT5F84EMhD6yzJmUYQV5Is= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 h1:X3NixTLN7+Oqn674kP8t96ztHUspl1CEliCY1bD8Kzk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:w2LKGIQfvocVKtQPmxoGi36ND4cKXicVlfpORu3Irjs= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320212435-efb51edcf7be h1:chFxoVQZSc817Ro4Oh2EQn1gbT8C7fxxBHh3bQW7bqQ= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320212435-efb51edcf7be/go.mod h1:mr+j2640RCvnXxPChwDH4BdvHCFXKuR+ogj2ePtNTWo= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 h1:2tWSQm0hl6n6cWAaL0MWs7xWYDe7/7/7Gz4ViBiuoQ0= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:18VZ5UrwiOZzMjqNvIHhZLZV640wYCP0X11h2wf8Uq4= +github.com/go-orb/plugins/config/source/file v0.1.1-0.20250324122813-09813c7b9d65 h1:0hJ6LxqnafPrJE/2rd9Fk2wKACRpqwd+Y4eBc3hYTK0= +github.com/go-orb/plugins/config/source/file v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:WL/+LubUXw4blqd/az/8/4X4m1QQgB4wOEPy2MObJsY= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 h1:Fj2tX19g5TxjS9pHyDV4ZMLkZYW4cuNJ6yh149HRJ84= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:U4rbrSlCGhQaiJxl4GRwIQLUv+Cg8og9NEEInd9j8ww= +github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65 h1:KyZnDOqU7JasAljrffIgweV60wJFJsaZi6TZG37H3Ak= +github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65/go.mod h1:cb1WD4avXpSEDYCcdx09hnj62lty2AeO5xe/1IlzuSE= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 h1:6pxnS4Kg1WRSMKU2DFVl40EFlO06YT7gT/d0uK8ZEB4= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:VLPoWEGe+/gcCUZnp3/WJXBP35C22+14CmjrIZegfQY= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122351-5903fde4d556 h1:d/Ma3w7xZE/BeJK7I65vwaA97bi0iy0EoyXNCA3bX/c= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122351-5903fde4d556/go.mod h1:qUq39uHPQ6qZZxNFtH3IPb01vWESqwSJrzUvrzAiBzc= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -37,6 +40,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8= +github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts= github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ= github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= diff --git a/server/grpc/grpc.go b/server/grpc/grpc.go index fc001e42..450259c1 100644 --- a/server/grpc/grpc.go +++ b/server/grpc/grpc.go @@ -22,7 +22,6 @@ import ( "github.com/go-orb/go-orb/log" "github.com/go-orb/go-orb/registry" "github.com/go-orb/go-orb/server" - "github.com/go-orb/go-orb/types" "github.com/go-orb/go-orb/util/addr" mnet "github.com/go-orb/go-orb/util/net" mtls "github.com/go-orb/go-orb/util/tls" @@ -33,6 +32,9 @@ var _ server.Entrypoint = (*Server)(nil) // Server is an entrypoint with a gRPC server. type Server struct { + serviceName string + serviceVersion string + server *grpc.Server config *Config @@ -51,6 +53,8 @@ type Server struct { // Provide provides a gRPC server by config. func Provide( + serviceName string, + serviceVersion string, configData map[string]any, logger log.Logger, reg registry.Type, @@ -77,11 +81,17 @@ func Provide( cfg.OptMiddlewares = append(cfg.OptMiddlewares, mw) } - return New(cfg, logger, reg) + return New(serviceName, serviceVersion, cfg, logger, reg) } // New creates a gRPC server by options. -func New(acfg any, logger log.Logger, reg registry.Type) (server.Entrypoint, error) { +func New( + serviceName string, + serviceVersion string, + acfg any, + logger log.Logger, + reg registry.Type, +) (server.Entrypoint, error) { cfg, ok := acfg.(*Config) if !ok { return nil, fmt.Errorf("grpc invalid config: %v", cfg) @@ -107,9 +117,11 @@ func New(acfg any, logger log.Logger, reg registry.Type) (server.Entrypoint, err } srv := Server{ - config: cfg, - logger: logger, - registry: reg, + serviceName: serviceName, + serviceVersion: serviceVersion, + config: cfg, + logger: logger, + registry: reg, } srv.setupgRPCServer() @@ -140,7 +152,7 @@ func (s *Server) setupgRPCServer() { } // Start start the gRPC server. -func (s *Server) Start(_ context.Context) error { +func (s *Server) Start(ctx context.Context) error { if s.started { return nil } @@ -181,7 +193,7 @@ func (s *Server) Start(_ context.Context) error { } // Register with registry. - if err := s.register(); err != nil { + if err := s.registryRegister(ctx); err != nil { return err } @@ -198,7 +210,7 @@ func (s *Server) Stop(ctx context.Context) error { s.logger.Info("gRPC server shutting down", "address", s.lis.Addr().String()) - if err := s.deregister(); err != nil { + if err := s.registryDeregister(ctx); err != nil { return err } @@ -249,11 +261,6 @@ func (s *Server) Transport() string { return "grpc" } -// EntrypointID returns the id of this entrypoint (node) in the registry. -func (s *Server) EntrypointID() string { - return s.registry.ServiceName() + types.DefaultSeparator + s.config.Name -} - // AddHandler adds a handler for later registration. func (s *Server) AddHandler(handler server.RegistrationFunc) { s.config.OptHandlers = append(s.config.OptHandlers, handler) @@ -317,45 +324,20 @@ func (s *Server) listen() error { return nil } -func (s *Server) getEndpoints() []*registry.Endpoint { - sInfo := s.server.GetServiceInfo() - - result := make([]*registry.Endpoint, 0, len(sInfo)) - - for k := range sInfo { - s.logger.Trace("found endpoint", slog.String("name", k)) - - result = append(result, ®istry.Endpoint{ - Name: k, - Metadata: map[string]string{"stream": "true"}, - }) - } - - return result -} - -func (s *Server) registryService() *registry.Service { - node := ®istry.Node{ - ID: s.EntrypointID(), - Address: s.Address(), - Transport: s.Transport(), - Metadata: make(map[string]string), - } - - eps := s.getEndpoints() - - return ®istry.Service{ - Name: s.registry.ServiceName(), - Version: s.registry.ServiceVersion(), - Nodes: []*registry.Node{node}, - Endpoints: eps, +func (s *Server) registryService() registry.ServiceNode { + return registry.ServiceNode{ + Name: s.serviceName, + Version: s.serviceVersion, + Address: s.Address(), + Scheme: s.Transport(), + Metadata: make(map[string]string), } } -func (s *Server) register() error { - return s.registry.Register(s.registryService()) +func (s *Server) registryRegister(ctx context.Context) error { + return s.registry.Register(ctx, s.registryService()) } -func (s *Server) deregister() error { - return s.registry.Deregister(s.registryService()) +func (s *Server) registryDeregister(ctx context.Context) error { + return s.registry.Deregister(ctx, s.registryService()) } diff --git a/server/grpc/tests/grpc_test.go b/server/grpc/tests/grpc_test.go index 7acb0805..2ae04eb8 100644 --- a/server/grpc/tests/grpc_test.go +++ b/server/grpc/tests/grpc_test.go @@ -20,11 +20,11 @@ import ( "github.com/go-orb/plugins/server/grpc/tests/proto" tgrpc "github.com/go-orb/plugins/server/grpc/tests/util/grpc" - _ "github.com/go-orb/plugins-experimental/registry/mdns" _ "github.com/go-orb/plugins/codecs/json" _ "github.com/go-orb/plugins/codecs/yaml" _ "github.com/go-orb/plugins/config/source/file" _ "github.com/go-orb/plugins/log/slog" + _ "github.com/go-orb/plugins/registry/mdns" ) func init() { @@ -93,11 +93,11 @@ func TestGrpcIntegration(t *testing.T) { logger, err := log.New() require.NoError(t, err, "failed to setup logger") - reg, err := registry.New(name, version, nil, components, logger) + reg, err := registry.New(nil, components, logger) require.NoError(t, err, "failed to setup the registry") h, _ := server.Handlers.Get("Streams") - srv, err := server.New(nil, logger, reg, + srv, err := server.New(name, version, nil, logger, reg, server.WithEntrypointConfig(mgrpc.NewConfig( mgrpc.WithName("test-ep-1"), mgrpc.WithReflection(true), @@ -160,11 +160,11 @@ func TestServerFileConfig(t *testing.T) { logger, err := log.New() require.NoError(t, err, "failed to setup logger") - reg, err := registry.New(name, version, nil, &types.Components{}, logger) + reg, err := registry.New(nil, &types.Components{}, logger) require.NoError(t, err, "failed to setup the registry") h, _ := server.Handlers.Get("Streams") - srv, err := server.New(configData, logger, reg, + srv, err := server.New(name, version, configData, logger, reg, server.WithEntrypointConfig(mgrpc.NewConfig( mgrpc.WithName("static-ep-1"), mgrpc.WithAddress(":48081"), diff --git a/server/grpc/tests/util/grpc/grpc.go b/server/grpc/tests/util/grpc/grpc.go index 194256a5..4371c52a 100644 --- a/server/grpc/tests/util/grpc/grpc.go +++ b/server/grpc/tests/util/grpc/grpc.go @@ -32,12 +32,12 @@ func SetupServer(opts ...server.Option) (server.Entrypoint, func(t *testing.T), components := types.NewComponents() - reg, err := registry.New("app", "v1.0.0", nil, components, logger) + reg, err := registry.New(nil, components, logger) if err != nil { return nil, nil, fmt.Errorf("setup registry: %w", err) } - srv, err := mgrpc.New(mgrpc.NewConfig(opts...), logger, reg) + srv, err := mgrpc.New("app", "v1.0.0", mgrpc.NewConfig(opts...), logger, reg) if err != nil { return nil, nil, fmt.Errorf("setup gRPC server: %w", err) } diff --git a/server/http/entrypoint.go b/server/http/entrypoint.go index f582ee39..364076bd 100644 --- a/server/http/entrypoint.go +++ b/server/http/entrypoint.go @@ -41,6 +41,9 @@ const Plugin = "http" // want to listen on multiple interfaces, or multiple ports in parallel, even // with the same handler. type Server struct { + serviceName string + serviceVersion string + config *Config logger log.Logger registry registry.Type @@ -68,6 +71,8 @@ type Server struct { // can serve a HTTP1, HTTP2 and HTTP3 server. If you enable HTTP3 it will listen // on both TCP and UDP on the same port. func Provide( + serviceName string, + serviceVersion string, configData map[string]any, logger log.Logger, reg registry.Type, @@ -104,11 +109,17 @@ func Provide( cfg.OptHandlers = append(cfg.OptHandlers, h) } - return New(cfg, logger, reg) + return New(serviceName, serviceVersion, cfg, logger, reg) } // New creates a http server by options. -func New(acfg any, logger log.Logger, reg registry.Type) (server.Entrypoint, error) { +func New( + serviceName string, + serviceVersion string, + acfg any, + logger log.Logger, + reg registry.Type, +) (server.Entrypoint, error) { cfg, ok := acfg.(*Config) if !ok { return nil, fmt.Errorf("http invalid config: %v", cfg) @@ -130,10 +141,12 @@ func New(acfg any, logger log.Logger, reg registry.Type) (server.Entrypoint, err logger = logger.With(slog.String("entrypoint", cfg.Name)) entrypoint := Server{ - config: cfg, - logger: logger, - registry: reg, - router: router, + serviceName: serviceName, + serviceVersion: serviceVersion, + config: cfg, + logger: logger, + registry: reg, + router: router, } entrypoint.config.TLS, err = entrypoint.setupTLS() @@ -154,7 +167,7 @@ func New(acfg any, logger log.Logger, reg registry.Type) (server.Entrypoint, err } // Start will create the listeners and start the server on the entrypoint. -func (s *Server) Start(_ context.Context) error { +func (s *Server) Start(ctx context.Context) error { if s.started { return nil } @@ -190,7 +203,7 @@ func (s *Server) Start(_ context.Context) error { }() if !s.config.HTTP3 { - if err := s.register(); err != nil { + if err := s.registryRegister(ctx); err != nil { return fmt.Errorf("failed to register the HTTP server: %w", err) } @@ -211,7 +224,7 @@ func (s *Server) Start(_ context.Context) error { } }() - if err := s.register(); err != nil { + if err := s.registryRegister(ctx); err != nil { return fmt.Errorf("failed to register the HTTP server: %w", err) } @@ -231,7 +244,7 @@ func (s *Server) Stop(ctx context.Context) error { s.logger.Debug("Stopping") - if err := s.deregister(); err != nil { + if err := s.registryDeregister(ctx); err != nil { return err } @@ -309,11 +322,6 @@ func (s *Server) Transport() string { return "http" } -// EntrypointID returns the id (configured name) of this entrypoint in the registry. -func (s *Server) EntrypointID() string { - return s.config.Name -} - // String returns the entrypoint type; http. func (s *Server) String() string { return Plugin @@ -362,58 +370,20 @@ func (s *Server) setupTLS() (*mtls.Config, error) { return &mtls.Config{Config: config}, nil } -//nolint:unparam -func (s *Server) getEndpoints() ([]*registry.Endpoint, error) { - routes := s.router.Routes() - result := make([]*registry.Endpoint, len(routes)) - - for _, r := range routes { - s.logger.Trace("found endpoint", slog.String("name", r)) - - result = append(result, ®istry.Endpoint{ - Name: r, - Metadata: map[string]string{"stream": "true"}, - }) - } - - return result, nil -} - -func (s *Server) registryService() (*registry.Service, error) { - node := ®istry.Node{ - ID: s.EntrypointID(), - Address: s.Address(), - Transport: s.Transport(), - Metadata: make(map[string]string), +func (s *Server) registryService() registry.ServiceNode { + return registry.ServiceNode{ + Name: s.serviceName, + Version: s.serviceVersion, + Address: s.Address(), + Scheme: s.Transport(), + Metadata: make(map[string]string), } - - eps, err := s.getEndpoints() - if err != nil { - return nil, err - } - - return ®istry.Service{ - Name: s.registry.ServiceName(), - Version: s.registry.ServiceVersion(), - Nodes: []*registry.Node{node}, - Endpoints: eps, - }, nil } -func (s *Server) register() error { - rService, err := s.registryService() - if err != nil { - return err - } - - return s.registry.Register(rService) +func (s *Server) registryRegister(ctx context.Context) error { + return s.registry.Register(ctx, s.registryService()) } -func (s *Server) deregister() error { - rService, err := s.registryService() - if err != nil { - return err - } - - return s.registry.Deregister(rService) +func (s *Server) registryDeregister(ctx context.Context) error { + return s.registry.Deregister(ctx, s.registryService()) } diff --git a/server/http/go.mod b/server/http/go.mod index e3fdd6e8..34c8ebea 100644 --- a/server/http/go.mod +++ b/server/http/go.mod @@ -3,32 +3,34 @@ module github.com/go-orb/plugins/server/http go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e - github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3 - github.com/go-orb/plugins/codecs/form v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/config/source/file v0.1.1-0.20250320235901-3af29c3a3b34 - github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 + github.com/go-orb/plugins/codecs/form v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/config/source/file v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 + github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65 github.com/julienschmidt/httprouter v1.3.0 github.com/pkg/errors v0.9.1 github.com/quic-go/quic-go v0.50.0 github.com/stretchr/testify v1.10.0 golang.org/x/net v0.37.0 - google.golang.org/protobuf v1.36.5 + google.golang.org/protobuf v1.36.6 ) require ( dario.cat/mergo v1.0.1 // indirect github.com/cornelk/hashmap v1.0.8 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 // indirect github.com/go-playground/form/v4 v4.2.2 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/pprof v0.0.0-20250302191652-9094ed2288e7 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/lithammer/shortuuid/v3 v3.0.7 // indirect github.com/miekg/dns v1.1.64 // indirect github.com/onsi/ginkgo/v2 v2.23.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect diff --git a/server/http/go.sum b/server/http/go.sum index f5918a34..6997f88a 100644 --- a/server/http/go.sum +++ b/server/http/go.sum @@ -6,24 +6,26 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= -github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3 h1:aK9T/j8iHppOp8DBUKW32s8/iz4rQm3OKgqM1tT8JVk= -github.com/go-orb/plugins-experimental/registry/mdns v0.0.0-20250320212500-13fd51a437b3/go.mod h1:A/CzKW0isS1OnxIvMYFJNR+kiEy519aP0o/ptr26HHo= -github.com/go-orb/plugins/codecs/form v0.1.1-0.20250320235901-3af29c3a3b34 h1:OqsMA3G7xrkzwMHAA/25S99aWQPnoz3Hia99cIt383I= -github.com/go-orb/plugins/codecs/form v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:SmJSzUHAbFecERTO/n95R8zQ8BCWJLK+L3Fcz6liQ8Y= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34 h1:i4hzlSlt7qTC8Qzgy5PLgDxNwy74FyPbLZhWRzpQgW4= -github.com/go-orb/plugins/codecs/json v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:QGhKBlq8+D9cKJT86tOlrUQC0W3h4QvEsr9YFfQ6a3A= -github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34 h1:VISuyjfVoNEBJmA0amnnnoluqJ+ACGfJQ8Z80NqoVvk= -github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:8DCvAVuNgQtbjfsXp6Wr3GcXw0yhearnn8KJIY6ph9I= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34 h1:auojRTYubvH+2JRLgE9I0O8nUrhT2e6sZpKv+IyoQ7U= -github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:RQ43qp8cY/yyfZ/rukmMVywaEb3IuC50Eq92qekmnUk= -github.com/go-orb/plugins/config/source/file v0.1.1-0.20250320235901-3af29c3a3b34 h1:KuPHiH1lkxdy4pzbXRjtBgf9X8S0l8eSaCPO5WMj/VE= -github.com/go-orb/plugins/config/source/file v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:4P+GclfUx1+m1Zur9EXKMXT5F84EMhD6yzJmUYQV5Is= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34 h1:X3NixTLN7+Oqn674kP8t96ztHUspl1CEliCY1bD8Kzk= -github.com/go-orb/plugins/log/slog v0.1.1-0.20250320235901-3af29c3a3b34/go.mod h1:w2LKGIQfvocVKtQPmxoGi36ND4cKXicVlfpORu3Irjs= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320212435-efb51edcf7be h1:chFxoVQZSc817Ro4Oh2EQn1gbT8C7fxxBHh3bQW7bqQ= -github.com/go-orb/plugins/registry/tests v0.1.1-0.20250320212435-efb51edcf7be/go.mod h1:mr+j2640RCvnXxPChwDH4BdvHCFXKuR+ogj2ePtNTWo= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/plugins/codecs/form v0.1.1-0.20250324122813-09813c7b9d65 h1:9Eo0RujlE+THHqDxVoDw0MDh92Io7qJnNgz+D78Hsv8= +github.com/go-orb/plugins/codecs/form v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:4JB11Si2zph/66aMluIbGOSKahBw+RH3tJo1y4vczho= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65 h1:MT3OmhhJAaZIRs+lLgTlBpZlkoV7yh5U4QL8gsCPFEc= +github.com/go-orb/plugins/codecs/json v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:i5OdWoJhfgFpBsXVHB2/uXxb36efccybiNTOgNzgNBE= +github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65 h1:XqBIBUzrQN2XJL7X0LabzFJ26h2Nzf25/owt/2upiW8= +github.com/go-orb/plugins/codecs/proto v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:a8/qGJJvPohXYQTnNt1VsQEaQsnOCJIa3sJmoATsTGo= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65 h1:2tWSQm0hl6n6cWAaL0MWs7xWYDe7/7/7Gz4ViBiuoQ0= +github.com/go-orb/plugins/codecs/yaml v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:18VZ5UrwiOZzMjqNvIHhZLZV640wYCP0X11h2wf8Uq4= +github.com/go-orb/plugins/config/source/file v0.1.1-0.20250324122813-09813c7b9d65 h1:0hJ6LxqnafPrJE/2rd9Fk2wKACRpqwd+Y4eBc3hYTK0= +github.com/go-orb/plugins/config/source/file v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:WL/+LubUXw4blqd/az/8/4X4m1QQgB4wOEPy2MObJsY= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65 h1:Fj2tX19g5TxjS9pHyDV4ZMLkZYW4cuNJ6yh149HRJ84= +github.com/go-orb/plugins/log/slog v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:U4rbrSlCGhQaiJxl4GRwIQLUv+Cg8og9NEEInd9j8ww= +github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65 h1:KyZnDOqU7JasAljrffIgweV60wJFJsaZi6TZG37H3Ak= +github.com/go-orb/plugins/registry/mdns v0.0.0-20250324122813-09813c7b9d65/go.mod h1:cb1WD4avXpSEDYCcdx09hnj62lty2AeO5xe/1IlzuSE= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65 h1:6pxnS4Kg1WRSMKU2DFVl40EFlO06YT7gT/d0uK8ZEB4= +github.com/go-orb/plugins/registry/regutil v0.1.1-0.20250324122813-09813c7b9d65/go.mod h1:VLPoWEGe+/gcCUZnp3/WJXBP35C22+14CmjrIZegfQY= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122351-5903fde4d556 h1:d/Ma3w7xZE/BeJK7I65vwaA97bi0iy0EoyXNCA3bX/c= +github.com/go-orb/plugins/registry/tests v0.1.1-0.20250324122351-5903fde4d556/go.mod h1:qUq39uHPQ6qZZxNFtH3IPb01vWESqwSJrzUvrzAiBzc= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -35,6 +37,7 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/pprof v0.0.0-20250302191652-9094ed2288e7 h1:+J3r2e8+RsmN3vKfo75g0YSY61ms37qzPglu4p0sGro= github.com/google/pprof v0.0.0-20250302191652-9094ed2288e7/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -48,6 +51,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8= +github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts= github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ= github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= github.com/onsi/ginkgo/v2 v2.23.0 h1:FA1xjp8ieYDzlgS5ABTpdUDB7wtngggONc8a7ku2NqQ= @@ -86,8 +91,8 @@ golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/server/http/tests/http_test.go b/server/http/tests/http_test.go index 74990c76..71117a2b 100644 --- a/server/http/tests/http_test.go +++ b/server/http/tests/http_test.go @@ -33,10 +33,10 @@ import ( _ "github.com/go-orb/plugins/codecs/json" _ "github.com/go-orb/plugins/codecs/proto" - _ "github.com/go-orb/plugins-experimental/registry/mdns" _ "github.com/go-orb/plugins/codecs/yaml" _ "github.com/go-orb/plugins/config/source/file" _ "github.com/go-orb/plugins/log/slog" + _ "github.com/go-orb/plugins/registry/mdns" ) // TODO(davincible): test get path params @@ -326,12 +326,12 @@ func TestServerIntegration(t *testing.T) { logger, err := log.New() require.NoError(t, err, "failed to setup the logger") - reg, err := registry.New(name, version, nil, components, logger) + reg, err := registry.New(nil, components, logger) require.NoError(t, err, "failed to setup the registry") h := new(handler.EchoHandler) - srv, err := server.New(nil, logger, reg, + srv, err := server.New(name, version, nil, logger, reg, server.WithEntrypointConfig(mhttp.NewConfig( mhttp.WithName("test-ep-1"), mhttp.WithAddress(":48081"), @@ -400,11 +400,11 @@ func TestServerFileConfig(t *testing.T) { logger, err := log.New() require.NoError(t, err, "failed to setup the logger") - reg, err := registry.New(name, version, nil, components, logger) + reg, err := registry.New(nil, components, logger) require.NoError(t, err, "failed to setup the registry") h := new(handler.EchoHandler) - srv, err := server.New(configData, logger, reg, + srv, err := server.New(name, version, configData, logger, reg, server.WithEntrypointConfig(mhttp.NewConfig( mhttp.WithName("static-ep-1"), mhttp.WithAddress(":48081"), @@ -649,7 +649,7 @@ func setupServer(tb testing.TB, nolog bool, opts ...server.Option) (*mhttp.Serve return nil, cancel, fmt.Errorf("failed to setup logger: %w", err) } - reg, err := registry.New(name, version, nil, components, logger) + reg, err := registry.New(nil, components, logger) if err != nil { return nil, nil, fmt.Errorf("setup registry: %w", err) } @@ -661,7 +661,7 @@ func setupServer(tb testing.TB, nolog bool, opts ...server.Option) (*mhttp.Serve cfg := mhttp.NewConfig(opts...) - server, err := mhttp.New(cfg, logger, reg) + server, err := mhttp.New(name, version, cfg, logger, reg) if err != nil { return nil, cancel, fmt.Errorf("failed to provide http server: %w", err) } diff --git a/server/memory/go.mod b/server/memory/go.mod index 92ac1f45..2be0fc8c 100644 --- a/server/memory/go.mod +++ b/server/memory/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/server/memory go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 github.com/zeebo/errs v1.4.0 storj.io/drpc v0.0.34 ) diff --git a/server/memory/go.sum b/server/memory/go.sum index ac8dee32..5f206086 100644 --- a/server/memory/go.sum +++ b/server/memory/go.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc= github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= diff --git a/server/memory/memory.go b/server/memory/memory.go index 5c3b92e0..a75e9faf 100644 --- a/server/memory/memory.go +++ b/server/memory/memory.go @@ -28,6 +28,9 @@ const Name = "memory" // Server is the memory Server for go-orb. type Server struct { + serviceName string + serviceVersion string + config *Config logger log.Logger registry registry.Type @@ -64,7 +67,7 @@ func (s *Server) Start(ctx context.Context) error { s.ctx, s.cancelFunc = context.WithCancel(ctx) // Register the memory server with the client package - client.RegisterMemoryServer(s.registry.ServiceName(), s) + client.RegisterMemoryServer(s.serviceName, s) s.started = true @@ -86,7 +89,7 @@ func (s *Server) Stop(_ context.Context) error { } // Unregister from the client package - client.UnregisterMemoryServer(s.registry.ServiceName()) + client.UnregisterMemoryServer(s.serviceName) // Clean up resources s.started = false @@ -126,11 +129,6 @@ func (s *Server) Transport() string { return "memory" } -// EntrypointID returns the id (configured name) of this entrypoint in the registry. -func (s *Server) EntrypointID() string { - return s.config.Name -} - // String returns the entrypoint type. func (s *Server) String() string { return s.Type() @@ -362,6 +360,8 @@ func (s *Server) Stream( // Provide creates a new entrypoint for a single address. You can create // multiple entrypoints for multiple addresses and ports. func Provide( + serviceName string, + serviceVersion string, configs map[string]any, logger log.Logger, reg registry.Type, @@ -398,11 +398,17 @@ func Provide( cfg.OptHandlers = append(cfg.OptHandlers, h) } - return New(cfg, logger, reg) + return New(serviceName, serviceVersion, cfg, logger, reg) } // New creates a memory Server from a Config struct. -func New(acfg any, logger log.Logger, reg registry.Type) (orbserver.Entrypoint, error) { +func New( + serviceName string, + serviceVersion string, + acfg any, + logger log.Logger, + reg registry.Type, +) (orbserver.Entrypoint, error) { cfg, ok := acfg.(*Config) if !ok { return nil, fmt.Errorf("memory invalid config: %v", cfg) @@ -413,13 +419,15 @@ func New(acfg any, logger log.Logger, reg registry.Type) (orbserver.Entrypoint, ctx, cancelFunc := context.WithCancel(context.Background()) entrypoint := Server{ - config: cfg, - logger: logger, - registry: reg, - handlers: cfg.OptHandlers, - middlewares: cfg.OptMiddlewares, - ctx: ctx, - cancelFunc: cancelFunc, + serviceName: serviceName, + serviceVersion: serviceVersion, + config: cfg, + logger: logger, + registry: reg, + handlers: cfg.OptHandlers, + middlewares: cfg.OptMiddlewares, + ctx: ctx, + cancelFunc: cancelFunc, } return &entrypoint, nil diff --git a/util/tests/go.mod b/util/tests/go.mod index a0d8e138..b9a98dc6 100644 --- a/util/tests/go.mod +++ b/util/tests/go.mod @@ -3,7 +3,7 @@ module github.com/go-orb/plugins/util/tests go 1.23.6 require ( - github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e + github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 github.com/stretchr/testify v1.10.0 ) diff --git a/util/tests/go.sum b/util/tests/go.sum index e72c03f6..10903684 100644 --- a/util/tests/go.sum +++ b/util/tests/go.sum @@ -1,8 +1,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e h1:/dzN721EqiJogdtjXVp0LBY2+daFm1p84PeB/fV9ya0= -github.com/go-orb/go-orb v0.2.2-0.20250320223438-2869142c7d3e/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8 h1:AoIUSRLgbOn+XNQu2nCV1xlwD33j3JgpUiMElOt7PgM= +github.com/go-orb/go-orb v0.2.2-0.20250324112306-5f5f154933b8/go.mod h1:DBamAST285wD+Ydbil1HGl9X19Sj+0xR1ZqFzKDxOgM= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=