diff --git a/pkg/services/reputation/local/route/calls.go b/pkg/services/reputation/local/route/calls.go index c239088ca..7ebcf8662 100644 --- a/pkg/services/reputation/local/route/calls.go +++ b/pkg/services/reputation/local/route/calls.go @@ -65,11 +65,13 @@ func (r *Router) InitWriter(ctx reputationcontroller.Context) (reputationcontrol }, nil } -func (w *trustWriter) Write(a reputation.Trust) error { +func (w *trustWriter) Write(t reputation.Trust) error { w.routeMtx.Lock() defer w.routeMtx.Unlock() - route, err := w.router.routeBuilder.NextStage(w.ctx.Epoch(), w.ctx.passedRoute) + localPeerID := reputation.PeerIDFromBytes(w.router.localSrvInfo.PublicKey()) + + route, err := w.router.routeBuilder.NextStage(w.ctx.Epoch(), localPeerID, w.ctx.passedRoute) if err != nil { return err } else if len(route) == 0 { @@ -106,7 +108,7 @@ func (w *trustWriter) Write(a reputation.Trust) error { w.mServers[endpoint] = remoteWriter } - err := remoteWriter.Write(a) + err := remoteWriter.Write(t) if err != nil { w.router.log.Debug("could not write the value", zap.String("error", err.Error()), diff --git a/pkg/services/reputation/local/route/deps.go b/pkg/services/reputation/local/route/deps.go index 0975f3812..701441df7 100644 --- a/pkg/services/reputation/local/route/deps.go +++ b/pkg/services/reputation/local/route/deps.go @@ -1,6 +1,7 @@ package reputationroute import ( + "github.com/nspcc-dev/neofs-node/pkg/services/reputation" reputationcontroller "github.com/nspcc-dev/neofs-node/pkg/services/reputation/local/controller" ) @@ -18,6 +19,18 @@ type ServerInfo interface { Address() string } +// Builder groups methods to route values in the network. +type Builder interface { + // NextStage must return next group of route points + // for passed epoch and PeerID of the current route point. + // Implementation must take into account already passed route points. + // + // Empty passed list means being at the starting point of the route. + // + // Must return empty list and no error if the endpoint of the route is reached. + NextStage(epoch uint64, p reputation.PeerID, passed []ServerInfo) ([]ServerInfo, error) +} + // RemoteWriterProvider describes the component // for sending values to a fixed route point. type RemoteWriterProvider interface { diff --git a/pkg/services/reputation/local/route/managers/builder.go b/pkg/services/reputation/local/route/managers/builder.go new file mode 100644 index 000000000..4aebfc6ad --- /dev/null +++ b/pkg/services/reputation/local/route/managers/builder.go @@ -0,0 +1,48 @@ +package managers + +import "fmt" + +// Prm groups the required parameters of the Builder's constructor. +// +// All values must comply with the requirements imposed on them. +// Passing incorrect parameter values will result in constructor +// failure (error or panic depending on the implementation). +type Prm struct { + // Manager builder for current node. + // + // Must not be nil. + ManagerBuilder ManagerBuilder +} + +// Builder represents component that routes node to its managers. +// +// For correct operation, Builder must be created using +// the constructor (New) based on the required parameters +// and optional components. After successful creation, +// the Builder is immediately ready to work through API. +type Builder struct { + managerBuilder ManagerBuilder +} + +const invalidPrmValFmt = "invalid parameter %s (%T):%v" + +func panicOnPrmValue(n string, v interface{}) { + panic(fmt.Sprintf(invalidPrmValFmt, n, v, v)) +} + +// New creates a new instance of the Builder. +// +// Panics if at least one value of the parameters is invalid. +// +// The created Builder does not require additional +// initialization and is completely ready for work. +func New(prm Prm) *Builder { + switch { + case prm.ManagerBuilder == nil: + panicOnPrmValue("ManagerBuilder", prm.ManagerBuilder) + } + + return &Builder{ + managerBuilder: prm.ManagerBuilder, + } +} diff --git a/pkg/services/reputation/local/route/managers/calls.go b/pkg/services/reputation/local/route/managers/calls.go new file mode 100644 index 000000000..0dcd3abef --- /dev/null +++ b/pkg/services/reputation/local/route/managers/calls.go @@ -0,0 +1,23 @@ +package managers + +import ( + "github.com/nspcc-dev/neofs-node/pkg/services/reputation" + reputationroute "github.com/nspcc-dev/neofs-node/pkg/services/reputation/local/route" + "github.com/pkg/errors" +) + +// NextStage builds Manager list for node and returns it directly. +// +// If passed route has more than one point, then endpoint of the route is reached. +func (b *Builder) NextStage(epoch uint64, p reputation.PeerID, passed []reputationroute.ServerInfo) ([]reputationroute.ServerInfo, error) { + if len(passed) > 1 { + return nil, nil + } + + route, err := b.managerBuilder.BuildManagers(epoch, p) + if err != nil { + return nil, errors.Wrapf(err, "could not build managers for epoch: %d", epoch) + } + + return route, nil +} diff --git a/pkg/services/reputation/local/route/managers/deps.go b/pkg/services/reputation/local/route/managers/deps.go new file mode 100644 index 000000000..135924da6 --- /dev/null +++ b/pkg/services/reputation/local/route/managers/deps.go @@ -0,0 +1,14 @@ +package managers + +import ( + "github.com/nspcc-dev/neofs-node/pkg/services/reputation" + reputationroute "github.com/nspcc-dev/neofs-node/pkg/services/reputation/local/route" +) + +// ManagerBuilder defines an interface for providing a list +// of Managers for specific epoch. Implementation depends on trust value. +type ManagerBuilder interface { + // BuildManagers must compose list of managers. It depends on + // particular epoch and PeerID of the current route point. + BuildManagers(epoch uint64, p reputation.PeerID) ([]reputationroute.ServerInfo, error) +}