[#255] ir: Make audit processor to push tasks to audit task manager

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2020-12-22 03:28:42 +03:00 committed by Alex Vanin
parent 580c9c974a
commit 4dc09b19f3
4 changed files with 103 additions and 1 deletions

View file

@ -17,9 +17,14 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/innerring/processors/netmap" "github.com/nspcc-dev/neofs-node/pkg/innerring/processors/netmap"
"github.com/nspcc-dev/neofs-node/pkg/innerring/timers" "github.com/nspcc-dev/neofs-node/pkg/innerring/timers"
"github.com/nspcc-dev/neofs-node/pkg/morph/client" "github.com/nspcc-dev/neofs-node/pkg/morph/client"
auditClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/audit"
auditWrapper "github.com/nspcc-dev/neofs-node/pkg/morph/client/audit/wrapper"
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "github.com/nspcc-dev/neofs-node/pkg/morph/event"
"github.com/nspcc-dev/neofs-node/pkg/morph/subscriber" "github.com/nspcc-dev/neofs-node/pkg/morph/subscriber"
auditSvc "github.com/nspcc-dev/neofs-node/pkg/services/audit"
audittask "github.com/nspcc-dev/neofs-node/pkg/services/audit/taskmanager"
"github.com/nspcc-dev/neofs-node/pkg/util/precision" "github.com/nspcc-dev/neofs-node/pkg/util/precision"
"github.com/panjf2000/ants/v2"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/viper" "github.com/spf13/viper"
"go.uber.org/atomic" "go.uber.org/atomic"
@ -44,11 +49,15 @@ type (
innerRingIndex atomic.Int32 innerRingIndex atomic.Int32
innerRingSize atomic.Int32 innerRingSize atomic.Int32
precision precision.Fixed8Converter precision precision.Fixed8Converter
auditClient *auditWrapper.ClientWrapper
// internal variables // internal variables
key *ecdsa.PrivateKey key *ecdsa.PrivateKey
pubKey []byte
contracts *contracts contracts *contracts
predefinedValidators []keys.PublicKey predefinedValidators []keys.PublicKey
workers []func(context.Context)
} }
contracts struct { contracts struct {
@ -115,15 +124,30 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) error {
go s.morphListener.ListenWithError(ctx, morphErr) // listen for neo:morph events go s.morphListener.ListenWithError(ctx, morphErr) // listen for neo:morph events
go s.mainnetListener.ListenWithError(ctx, mainnnetErr) // listen for neo:mainnet events go s.mainnetListener.ListenWithError(ctx, mainnnetErr) // listen for neo:mainnet events
s.startWorkers(ctx)
return nil return nil
} }
func (s *Server) startWorkers(ctx context.Context) {
for _, w := range s.workers {
go w(ctx)
}
}
// Stop closes all subscription channels. // Stop closes all subscription channels.
func (s *Server) Stop() { func (s *Server) Stop() {
go s.morphListener.Stop() go s.morphListener.Stop()
go s.mainnetListener.Stop() go s.mainnetListener.Stop()
} }
func (s *Server) WriteReport(r *auditSvc.Report) error {
res := r.Result()
res.SetPublicKey(s.pubKey)
return s.auditClient.PutAuditResult(res)
}
// New creates instance of inner ring sever structure. // New creates instance of inner ring sever structure.
func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error) { func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error) {
var err error var err error
@ -189,6 +213,28 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error
return nil, err return nil, err
} }
server.pubKey = crypto.MarshalPublicKey(&server.key.PublicKey)
auditPool, err := ants.NewPool(cfg.GetInt("audit.task.exec_pool_size"), ants.WithNonblocking(true))
if err != nil {
return nil, err
}
staticAuditClient, err := client.NewStatic(server.morphClient, server.contracts.audit, 0)
if err != nil {
return nil, err
}
server.auditClient = auditWrapper.WrapClient(auditClient.New(staticAuditClient))
auditTaskManager := audittask.New(
audittask.WithQueueCapacity(cfg.GetUint32("audit.task.queue_capacity")),
audittask.WithWorkerPool(auditPool),
audittask.WithLogger(log),
)
server.workers = append(server.workers, auditTaskManager.Listen)
// create audit processor // create audit processor
auditProcessor, err := audit.New(&audit.Params{ auditProcessor, err := audit.New(&audit.Params{
Log: log, Log: log,
@ -198,6 +244,8 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error
MorphClient: server.morphClient, MorphClient: server.morphClient,
IRList: server, IRList: server,
ClientCache: newClientCache(server.key), ClientCache: newClientCache(server.key),
TaskManager: auditTaskManager,
Reporter: server,
}) })
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -10,6 +10,7 @@ import (
"github.com/nspcc-dev/neofs-api-go/pkg/netmap" "github.com/nspcc-dev/neofs-api-go/pkg/netmap"
"github.com/nspcc-dev/neofs-api-go/pkg/object" "github.com/nspcc-dev/neofs-api-go/pkg/object"
"github.com/nspcc-dev/neofs-node/pkg/network" "github.com/nspcc-dev/neofs-node/pkg/network"
"github.com/nspcc-dev/neofs-node/pkg/services/audit"
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/storagegroup" "github.com/nspcc-dev/neofs-node/pkg/services/object_manager/storagegroup"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -19,6 +20,8 @@ var sgFilter = storagegroup.SearchQuery()
func (ap *Processor) processStartAudit(epoch uint64) { func (ap *Processor) processStartAudit(epoch uint64) {
log := ap.log.With(zap.Uint64("epoch", epoch)) log := ap.log.With(zap.Uint64("epoch", epoch))
ap.prevAuditCanceler()
containers, err := ap.selectContainersToAudit(epoch) containers, err := ap.selectContainersToAudit(epoch)
if err != nil { if err != nil {
log.Error("container selection failure", zap.String("error", err.Error())) log.Error("container selection failure", zap.String("error", err.Error()))
@ -68,7 +71,25 @@ func (ap *Processor) processStartAudit(epoch uint64) {
zap.Stringer("cid", containers[i]), zap.Stringer("cid", containers[i]),
zap.Int("amount", len(storageGroups))) zap.Int("amount", len(storageGroups)))
// todo: for each container push audit tasks into queue var auditCtx context.Context
auditCtx, ap.prevAuditCanceler = context.WithCancel(context.Background())
auditTask := new(audit.Task).
WithReporter(&epochAuditReporter{
epoch: epoch,
rep: ap.reporter,
}).
WithAuditContext(auditCtx).
WithContainerID(containers[i]).
WithStorageGroupList(storageGroups).
WithContainerStructure(cnr).
WithContainerNodes(nodes)
if err := ap.taskManager.PushTask(auditTask); err != nil {
ap.log.Error("could not push audit task",
zap.String("error", err.Error()),
)
}
} }
} }

View file

@ -1,6 +1,8 @@
package audit package audit
import ( import (
"context"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
SDKClient "github.com/nspcc-dev/neofs-api-go/pkg/client" SDKClient "github.com/nspcc-dev/neofs-api-go/pkg/client"
"github.com/nspcc-dev/neofs-node/pkg/innerring/invoke" "github.com/nspcc-dev/neofs-node/pkg/innerring/invoke"
@ -8,6 +10,7 @@ import (
wrapContainer "github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper" wrapContainer "github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
wrapNetmap "github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap/wrapper" wrapNetmap "github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap/wrapper"
"github.com/nspcc-dev/neofs-node/pkg/morph/event" "github.com/nspcc-dev/neofs-node/pkg/morph/event"
"github.com/nspcc-dev/neofs-node/pkg/services/audit"
"github.com/panjf2000/ants/v2" "github.com/panjf2000/ants/v2"
"github.com/pkg/errors" "github.com/pkg/errors"
"go.uber.org/zap" "go.uber.org/zap"
@ -25,6 +28,10 @@ type (
Get(address string, opts ...SDKClient.Option) (*SDKClient.Client, error) Get(address string, opts ...SDKClient.Option) (*SDKClient.Client, error)
} }
TaskManager interface {
PushTask(*audit.Task) error
}
// Processor of events related with data audit. // Processor of events related with data audit.
Processor struct { Processor struct {
log *zap.Logger log *zap.Logger
@ -37,6 +44,10 @@ type (
containerClient *wrapContainer.Wrapper containerClient *wrapContainer.Wrapper
netmapClient *wrapNetmap.Wrapper netmapClient *wrapNetmap.Wrapper
taskManager TaskManager
reporter audit.Reporter
prevAuditCanceler context.CancelFunc
} }
// Params of the processor constructor. // Params of the processor constructor.
@ -48,9 +59,17 @@ type (
MorphClient *client.Client MorphClient *client.Client
IRList Indexer IRList Indexer
ClientCache NeoFSClientCache ClientCache NeoFSClientCache
TaskManager TaskManager
Reporter audit.Reporter
} }
) )
type epochAuditReporter struct {
epoch uint64
rep audit.Reporter
}
// AuditProcessor manages audit tasks and fills queue for next epoch. This // AuditProcessor manages audit tasks and fills queue for next epoch. This
// process must not be interrupted by new audit epoch, so we limit pool size // process must not be interrupted by new audit epoch, so we limit pool size
// for processor to one. // for processor to one.
@ -96,6 +115,9 @@ func New(p *Params) (*Processor, error) {
clientCache: p.ClientCache, clientCache: p.ClientCache,
containerClient: containerClient, containerClient: containerClient,
netmapClient: netmapClient, netmapClient: netmapClient,
taskManager: p.TaskManager,
reporter: p.Reporter,
prevAuditCanceler: func() {},
}, nil }, nil
} }
@ -118,3 +140,10 @@ func (ap *Processor) TimersHandlers() []event.HandlerInfo {
func (ap *Processor) StartAuditHandler() event.Handler { func (ap *Processor) StartAuditHandler() event.Handler {
return ap.handleNewAuditRound return ap.handleNewAuditRound
} }
func (r *epochAuditReporter) WriteReport(rep *audit.Report) error {
res := rep.Result()
res.SetAuditEpoch(r.epoch)
return r.rep.WriteReport(rep)
}

View file

@ -6,6 +6,7 @@ import (
"github.com/nspcc-dev/neofs-api-go/pkg/container" "github.com/nspcc-dev/neofs-api-go/pkg/container"
"github.com/pkg/errors" "github.com/pkg/errors"
"go.uber.org/zap"
) )
var ErrInvalidIRNode = errors.New("node is not in the inner ring list") var ErrInvalidIRNode = errors.New("node is not in the inner ring list")
@ -18,6 +19,9 @@ func (ap *Processor) selectContainersToAudit(epoch uint64) ([]*container.ID, err
// consider getting extra information about container complexity from // consider getting extra information about container complexity from
// audit contract there // audit contract there
ap.log.Debug("container listing finished",
zap.Int("total amount", len(containers)),
)
sort.Slice(containers, func(i, j int) bool { sort.Slice(containers, func(i, j int) bool {
return strings.Compare(containers[i].String(), containers[j].String()) < 0 return strings.Compare(containers[i].String(), containers[j].String()) < 0