[#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, subs map[event.Type][]event.Handler,
) { ) {
for typ, handlers := range subs { for typ, handlers := range subs {
pi := event.NotificationParserInfo{} hi := event.NotificationHandlerInfo{}
pi.SetType(typ) hi.SetType(typ)
pi.SetScriptHash(scHash) hi.SetScriptHash(scHash)
p, ok := parsers[typ] p, ok := parsers[typ]
if !ok { if !ok {
panic(fmt.Sprintf("missing parser for event %s", typ)) panic(fmt.Sprintf("missing parser for event %s", typ))
} }
pi.SetParser(p) hi.SetParser(p)
lis.SetNotificationParser(pi)
for _, h := range handlers { for _, h := range handlers {
hi := event.NotificationHandlerInfo{} hi.AddHandler(h)
hi.SetType(typ)
hi.SetScriptHash(scHash)
hi.SetHandler(h)
lis.RegisterNotificationHandler(hi)
} }
lis.RegisterNotificationHandler(hi)
} }
} }

View file

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

View file

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

View file

@ -114,11 +114,6 @@ func (ap *Processor) SetParsedWallets(parsedWallets []util.Uint160) {
ap.pwLock.Unlock() 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. // ListenerNotificationHandlers for the 'event.Listener' event producer.
func (ap *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { func (ap *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
return nil return nil

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -33,13 +33,6 @@ type Listener interface {
// it could not be started. // it could not be started.
ListenWithError(context.Context, chan<- error) 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. // 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. // 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) 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. // RegisterNotificationHandler registers the handler for particular notification event of contract.
// //
// Ignores nil handlers. // Ignores nil handlers.
@ -476,22 +448,14 @@ func (l *listener) RegisterNotificationHandler(hi NotificationHandlerInfo) {
) )
// check if parser was set // 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() l.mtx.Lock()
defer l.mtx.Unlock()
l.notificationParsers[hi.scriptHashWithType] = hi.parser
l.notificationHandlers[hi.scriptHashWithType] = append( l.notificationHandlers[hi.scriptHashWithType] = append(
l.notificationHandlers[hi.scriptHashWithType], l.notificationHandlers[hi.scriptHashWithType],
hi.Handler(), hi.handlers...,
) )
l.mtx.Unlock()
log.Debug(context.Background(), logs.EventRegisteredNewEventHandler) 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) notificationHandled := make(chan bool)
handledNotifications := make([]Event, 0) handledNotifications := make([]Event, 0)
l.RegisterNotificationHandler(NotificationHandlerInfo{ l.RegisterNotificationHandler(NotificationHandlerInfo{
scriptHashWithType: key, 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) handledNotifications = append(handledNotifications, e)
notificationHandled <- true notificationHandled <- true
}, },
},
}) })
go list.Listen(context.Background()) go list.Listen(context.Background())

View file

@ -11,15 +11,6 @@ import (
// from the StackItem list. // from the StackItem list.
type NotificationParser func(*state.ContainedNotificationEvent) (Event, error) 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 // NotaryPreparator constructs NotaryEvent
// from the NotaryRequest event. // from the NotaryRequest event.
type NotaryPreparator interface { type NotaryPreparator interface {
@ -47,24 +38,6 @@ func (n *NotaryParserInfo) SetParser(p NotaryParser) {
n.p = p 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 { type wrongPrmNumber struct {
exp, act int exp, act int
} }