frostfs-node/pkg/services/tree/redirect.go
Evgenii Stratonikov bc8d79ddf9
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 3m7s
DCO action / DCO (pull_request) Successful in 3m18s
Vulncheck / Vulncheck (pull_request) Successful in 3m22s
Tests and linters / Staticcheck (pull_request) Successful in 4m25s
Pre-commit hooks / Pre-commit (pull_request) Successful in 5m11s
Tests and linters / Lint (pull_request) Successful in 5m13s
Build / Build Components (pull_request) Successful in 5m19s
Tests and linters / gopls check (pull_request) Successful in 6m12s
Tests and linters / Tests (pull_request) Successful in 6m58s
Tests and linters / Tests with -race (pull_request) Successful in 6m59s
[#1447] services/tree: Move relaying code to a separate function
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-10-24 10:01:03 +03:00

72 lines
2 KiB
Go

package tree
import (
"bytes"
"context"
"errors"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap"
"google.golang.org/grpc"
)
var errNoSuitableNode = errors.New("no node was found to execute the request")
func relayUnary[Req any, Resp any](ctx context.Context, s *Service, ns []netmapSDK.NodeInfo, req *Req, callback func(TreeServiceClient, context.Context, *Req, ...grpc.CallOption) (*Resp, error)) (*Resp, error) {
var resp *Resp
var outErr error
err := s.forEachNode(ctx, ns, func(c TreeServiceClient) bool {
resp, outErr = callback(c, ctx, req)
return true
})
if err != nil {
return nil, err
}
return resp, outErr
}
// forEachNode executes callback for each node in the container until true is returned.
// Returns errNoSuitableNode if there was no successful attempt to dial any node.
func (s *Service) forEachNode(ctx context.Context, cntNodes []netmapSDK.NodeInfo, f func(c TreeServiceClient) bool) error {
for _, n := range cntNodes {
if bytes.Equal(n.PublicKey(), s.rawPub) {
return nil
}
}
var called bool
for _, n := range cntNodes {
var stop bool
n.IterateNetworkEndpoints(func(endpoint string) bool {
ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.IterateNetworkEndpoints",
trace.WithAttributes(
attribute.String("endpoint", endpoint),
))
defer span.End()
c, err := s.cache.get(ctx, endpoint)
if err != nil {
return false
}
s.log.Debug(logs.TreeRedirectingTreeServiceQuery, zap.String("endpoint", endpoint),
zap.String("trace_id", tracingPkg.GetTraceID(ctx)))
called = true
stop = f(c)
return true
})
if stop {
return nil
}
}
if !called {
return errNoSuitableNode
}
return nil
}