[#1546] morph/event: Merge notification parser and handlers

They are decoupled, but it is an error to have a handler without a
corresponding parser. Register them together on the code level and get
rid of unreachable code.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
Evgenii Stratonikov 2024-12-06 16:01:16 +03:00 committed by Evgenii Stratonikov
parent dfa51048a8
commit d0ce835fbf
13 changed files with 44 additions and 191 deletions

View file

@ -223,27 +223,21 @@ func registerNotificationHandlers(scHash util.Uint160, lis event.Listener, parse
subs map[event.Type][]event.Handler,
) {
for typ, handlers := range subs {
pi := event.NotificationParserInfo{}
pi.SetType(typ)
pi.SetScriptHash(scHash)
hi := event.NotificationHandlerInfo{}
hi.SetType(typ)
hi.SetScriptHash(scHash)
p, ok := parsers[typ]
if !ok {
panic(fmt.Sprintf("missing parser for event %s", typ))
}
pi.SetParser(p)
lis.SetNotificationParser(pi)
hi.SetParser(p)
for _, h := range handlers {
hi := event.NotificationHandlerInfo{}
hi.SetType(typ)
hi.SetScriptHash(scHash)
hi.SetHandler(h)
lis.RegisterNotificationHandler(hi)
hi.AddHandler(h)
}
lis.RegisterNotificationHandler(hi)
}
}

View file

@ -165,7 +165,6 @@ const (
EventCouldNotParseNotaryEvent = "could not parse notary event"
EventNotaryHandlersForParsedNotificationEventWereNotRegistered = "notary handlers for parsed notification event were not registered"
EventRegisteredNewEventParser = "registered new event parser"
EventIgnoreHandlerOfEventWoParser = "ignore handler of event w/o parser"
EventRegisteredNewEventHandler = "registered new event handler"
EventIgnoreHandlerOfNotaryEventWoParser = "ignore handler of notary event w/o parser"
StorageOperation = "local object storage operation"

View file

@ -8,7 +8,6 @@ type (
// ContractProcessor interface defines functions for binding event producers
// such as event.Listener and Timers with contract processor.
ContractProcessor interface {
ListenerNotificationParsers() []event.NotificationParserInfo
ListenerNotificationHandlers() []event.NotificationHandlerInfo
ListenerNotaryParsers() []event.NotaryParserInfo
ListenerNotaryHandlers() []event.NotaryHandlerInfo
@ -16,11 +15,6 @@ type (
)
func connectListenerWithProcessor(l event.Listener, p ContractProcessor) {
// register notification parsers
for _, parser := range p.ListenerNotificationParsers() {
l.SetNotificationParser(parser)
}
// register notification handlers
for _, handler := range p.ListenerNotificationHandlers() {
l.RegisterNotificationHandler(handler)

View file

@ -114,11 +114,6 @@ func (ap *Processor) SetParsedWallets(parsedWallets []util.Uint160) {
ap.pwLock.Unlock()
}
// ListenerNotificationParsers for the 'event.Listener' event producer.
func (ap *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
return nil
}
// ListenerNotificationHandlers for the 'event.Listener' event producer.
func (ap *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
return nil

View file

@ -88,20 +88,6 @@ func New(p *Params) (*Processor, error) {
}, nil
}
// ListenerNotificationParsers for the 'event.Listener' event producer.
func (bp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
var parsers []event.NotificationParserInfo
// new lock event
lock := event.NotificationParserInfo{}
lock.SetType(lockNotification)
lock.SetScriptHash(bp.balanceSC)
lock.SetParser(balanceEvent.ParseLock)
parsers = append(parsers, lock)
return parsers
}
// ListenerNotificationHandlers for the 'event.Listener' event producer.
func (bp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
var handlers []event.NotificationHandlerInfo
@ -110,7 +96,8 @@ func (bp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI
lock := event.NotificationHandlerInfo{}
lock.SetType(lockNotification)
lock.SetScriptHash(bp.balanceSC)
lock.SetHandler(bp.handleLock)
lock.SetParser(balanceEvent.ParseLock)
lock.AddHandler(bp.handleLock)
handlers = append(handlers, lock)
return handlers

View file

@ -118,11 +118,6 @@ func New(p *Params) (*Processor, error) {
}, nil
}
// ListenerNotificationParsers for the 'event.Listener' event producer.
func (cp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
return nil
}
// ListenerNotificationHandlers for the 'event.Listener' event producer.
func (cp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
return nil

View file

@ -142,39 +142,6 @@ func New(p *Params) (*Processor, error) {
}, nil
}
// ListenerNotificationParsers for the 'event.Listener' event producer.
func (np *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
var (
parsers = make([]event.NotificationParserInfo, 0, 6)
p event.NotificationParserInfo
)
p.SetScriptHash(np.frostfsContract)
// deposit event
p.SetType(event.TypeFromString(depositNotification))
p.SetParser(frostfsEvent.ParseDeposit)
parsers = append(parsers, p)
// withdraw event
p.SetType(event.TypeFromString(withdrawNotification))
p.SetParser(frostfsEvent.ParseWithdraw)
parsers = append(parsers, p)
// cheque event
p.SetType(event.TypeFromString(chequeNotification))
p.SetParser(frostfsEvent.ParseCheque)
parsers = append(parsers, p)
// config event
p.SetType(event.TypeFromString(configNotification))
p.SetParser(frostfsEvent.ParseConfig)
parsers = append(parsers, p)
return parsers
}
// ListenerNotificationHandlers for the 'event.Listener' event producer.
func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
var (
@ -187,22 +154,26 @@ func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI
// deposit handler
h.SetType(event.TypeFromString(depositNotification))
h.SetHandler(np.handleDeposit)
h.SetParser(frostfsEvent.ParseDeposit)
h.AddHandler(np.handleDeposit)
handlers = append(handlers, h)
// withdraw handler
h.SetType(event.TypeFromString(withdrawNotification))
h.SetHandler(np.handleWithdraw)
h.SetParser(frostfsEvent.ParseWithdraw)
h.AddHandler(np.handleWithdraw)
handlers = append(handlers, h)
// cheque handler
h.SetType(event.TypeFromString(chequeNotification))
h.SetHandler(np.handleCheque)
h.SetParser(frostfsEvent.ParseCheque)
h.AddHandler(np.handleCheque)
handlers = append(handlers, h)
// config handler
h.SetType(event.TypeFromString(configNotification))
h.SetHandler(np.handleConfig)
h.SetParser(frostfsEvent.ParseConfig)
h.AddHandler(np.handleConfig)
handlers = append(handlers, h)
return handlers

View file

@ -155,21 +155,13 @@ func New(p *Params) (*Processor, error) {
}, nil
}
// ListenerNotificationParsers for the 'event.Listener' event producer.
func (gp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
var pi event.NotificationParserInfo
pi.SetScriptHash(gp.designate)
pi.SetType(event.TypeFromString(native.DesignationEventName))
pi.SetParser(rolemanagement.ParseDesignate)
return []event.NotificationParserInfo{pi}
}
// ListenerNotificationHandlers for the 'event.Listener' event producer.
func (gp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
var hi event.NotificationHandlerInfo
hi.SetScriptHash(gp.designate)
hi.SetType(event.TypeFromString(native.DesignationEventName))
hi.SetHandler(gp.HandleAlphabetSync)
hi.SetParser(rolemanagement.ParseDesignate)
hi.AddHandler(gp.HandleAlphabetSync)
return []event.NotificationHandlerInfo{hi}
}

View file

@ -161,22 +161,6 @@ func New(p *Params) (*Processor, error) {
}, nil
}
// ListenerNotificationParsers for the 'event.Listener' event producer.
func (np *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
parsers := make([]event.NotificationParserInfo, 0, 3)
var p event.NotificationParserInfo
p.SetScriptHash(np.netmapClient.ContractAddress())
// new epoch event
p.SetType(newEpochNotification)
p.SetParser(netmapEvent.ParseNewEpoch)
parsers = append(parsers, p)
return parsers
}
// ListenerNotificationHandlers for the 'event.Listener' event producer.
func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
handlers := make([]event.NotificationHandlerInfo, 0, 3)
@ -187,7 +171,8 @@ func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI
// new epoch handler
i.SetType(newEpochNotification)
i.SetHandler(np.handleNewEpoch)
i.SetParser(netmapEvent.ParseNewEpoch)
i.AddHandler(np.handleNewEpoch)
handlers = append(handlers, i)
return handlers

View file

@ -18,17 +18,23 @@ type BlockHandler func(context.Context, *block.Block)
type NotificationHandlerInfo struct {
scriptHashWithType
h Handler
parser NotificationParser
handlers []Handler
}
// SetHandler is an event handler setter.
func (s *NotificationHandlerInfo) SetHandler(v Handler) {
s.h = v
// SetParser is an event handler setter.
func (s *NotificationHandlerInfo) SetParser(p NotificationParser) {
s.parser = p
}
// AddHandler adds an event handler.
func (s *NotificationHandlerInfo) AddHandler(v Handler) {
s.handlers = append(s.handlers, v)
}
// Handler returns an event handler.
func (s NotificationHandlerInfo) Handler() Handler {
return s.h
func (s NotificationHandlerInfo) Handlers() []Handler {
return s.handlers
}
// NotaryHandlerInfo is a structure that groups

View file

@ -33,13 +33,6 @@ type Listener interface {
// it could not be started.
ListenWithError(context.Context, chan<- error)
// SetNotificationParser must set the parser of particular contract event.
//
// Parser of each event must be set once. All parsers must be set before Listen call.
//
// Must ignore nil parsers and all calls after listener has been started.
SetNotificationParser(NotificationParserInfo)
// RegisterNotificationHandler must register the event handler for particular notification event of contract.
//
// The specified handler must be called after each capture and parsing of the event.
@ -444,27 +437,6 @@ func (l *listener) parseAndHandleNotary(ctx context.Context, nr *result.NotaryRe
handler(ctx, event)
}
// SetNotificationParser sets the parser of particular contract event.
//
// Ignores nil and already set parsers.
// Ignores the parser if listener is started.
func (l *listener) SetNotificationParser(pi NotificationParserInfo) {
log := l.log.With(
zap.String("contract", pi.ScriptHash().StringLE()),
zap.Stringer("event_type", pi.getType()),
)
l.mtx.Lock()
defer l.mtx.Unlock()
// add event parser
if _, ok := l.notificationParsers[pi.scriptHashWithType]; !ok {
l.notificationParsers[pi.scriptHashWithType] = pi.parser()
}
log.Debug(context.Background(), logs.EventRegisteredNewEventParser)
}
// RegisterNotificationHandler registers the handler for particular notification event of contract.
//
// Ignores nil handlers.
@ -476,22 +448,14 @@ func (l *listener) RegisterNotificationHandler(hi NotificationHandlerInfo) {
)
// check if parser was set
l.mtx.RLock()
_, ok := l.notificationParsers[hi.scriptHashWithType]
l.mtx.RUnlock()
if !ok {
log.Warn(context.Background(), logs.EventIgnoreHandlerOfEventWoParser)
return
}
// add event handler
l.mtx.Lock()
defer l.mtx.Unlock()
l.notificationParsers[hi.scriptHashWithType] = hi.parser
l.notificationHandlers[hi.scriptHashWithType] = append(
l.notificationHandlers[hi.scriptHashWithType],
hi.Handler(),
hi.handlers...,
)
l.mtx.Unlock()
log.Debug(context.Background(), logs.EventRegisteredNewEventHandler)
}

View file

@ -48,21 +48,19 @@ func TestEventHandling(t *testing.T) {
},
}
l.SetNotificationParser(NotificationParserInfo{
scriptHashWithType: key,
p: func(cne *state.ContainedNotificationEvent) (Event, error) {
return testNotificationEvent{source: cne}, nil
},
})
notificationHandled := make(chan bool)
handledNotifications := make([]Event, 0)
l.RegisterNotificationHandler(NotificationHandlerInfo{
scriptHashWithType: key,
h: func(_ context.Context, e Event) {
parser: func(cne *state.ContainedNotificationEvent) (Event, error) {
return testNotificationEvent{source: cne}, nil
},
handlers: []Handler{
func(_ context.Context, e Event) {
handledNotifications = append(handledNotifications, e)
notificationHandled <- true
},
},
})
go list.Listen(context.Background())

View file

@ -11,15 +11,6 @@ import (
// from the StackItem list.
type NotificationParser func(*state.ContainedNotificationEvent) (Event, error)
// NotificationParserInfo is a structure that groups
// the parameters of particular contract
// notification event parser.
type NotificationParserInfo struct {
scriptHashWithType
p NotificationParser
}
// NotaryPreparator constructs NotaryEvent
// from the NotaryRequest event.
type NotaryPreparator interface {
@ -47,24 +38,6 @@ func (n *NotaryParserInfo) SetParser(p NotaryParser) {
n.p = p
}
// SetParser is an event parser setter.
func (s *NotificationParserInfo) SetParser(v NotificationParser) {
s.p = v
}
func (s NotificationParserInfo) parser() NotificationParser {
return s.p
}
// SetType is an event type setter.
func (s *NotificationParserInfo) SetType(v Type) {
s.typ = v
}
func (s NotificationParserInfo) getType() Type {
return s.typ
}
type wrongPrmNumber struct {
exp, act int
}