[WIP]: broker ErrorHandler option (#1296)

* broker ErrorHandler option

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* rewrite Event interface, add error

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* implement new interface

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* change ErrorHandler func to broker.Handler

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* fix

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2020-03-07 00:25:16 +03:00 committed by GitHub
parent 11be2c68b9
commit 8ee5607254
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 94 additions and 14 deletions

View File

@ -28,6 +28,7 @@ type Event interface {
Topic() string Topic() string
Message() *Message Message() *Message
Ack() error Ack() error
Error() error
} }
// Subscriber is a convenience return type for the Subscribe method // Subscriber is a convenience return type for the Subscribe method

View File

@ -54,6 +54,7 @@ type subscriber struct {
type publication struct { type publication struct {
t string t string
err error
m *Message m *Message
} }
@ -70,6 +71,10 @@ func (p *publication) Ack() error {
return nil return nil
} }
func (p *publication) Error() error {
return p.err
}
func (s *subscriber) Options() SubscribeOptions { func (s *subscriber) Options() SubscribeOptions {
return s.opts return s.opts
} }
@ -390,10 +395,26 @@ func (n *natsBroker) Subscribe(topic string, handler Handler, opts ...SubscribeO
fn := func(msg *nats.Msg) { fn := func(msg *nats.Msg) {
var m Message var m Message
if err := n.opts.Codec.Unmarshal(msg.Data, &m); err != nil { pub := &publication{t: msg.Subject}
eh := n.opts.ErrorHandler
err := n.opts.Codec.Unmarshal(msg.Data, &m)
pub.err = err
pub.m = &m
if err != nil {
m.Body = msg.Data
log.Error(err)
if eh != nil {
eh(pub)
}
return return
} }
handler(&publication{m: &m, t: msg.Subject}) if err := handler(pub); err != nil {
pub.err = err
log.Error(err)
if eh != nil {
eh(pub)
}
}
} }
var sub *nats.Subscription var sub *nats.Subscription

View File

@ -27,6 +27,7 @@ type memoryBroker struct {
type memoryEvent struct { type memoryEvent struct {
opts broker.Options opts broker.Options
topic string topic string
err error
message interface{} message interface{}
} }
@ -120,6 +121,11 @@ func (m *memoryBroker) Publish(topic string, msg *broker.Message, opts ...broker
for _, sub := range subs { for _, sub := range subs {
if err := sub.handler(p); err != nil { if err := sub.handler(p); err != nil {
p.err = err
if eh := m.opts.ErrorHandler; eh != nil {
eh(p)
continue
}
return err return err
} }
} }
@ -197,6 +203,10 @@ func (m *memoryEvent) Ack() error {
return nil return nil
} }
func (m *memoryEvent) Error() error {
return m.err
}
func (m *memorySubscriber) Options() broker.SubscribeOptions { func (m *memorySubscriber) Options() broker.SubscribeOptions {
return m.opts return m.opts
} }

View File

@ -51,6 +51,7 @@ type subscriber struct {
type publication struct { type publication struct {
t string t string
err error
m *broker.Message m *broker.Message
} }
@ -67,6 +68,10 @@ func (p *publication) Ack() error {
return nil return nil
} }
func (p *publication) Error() error {
return p.err
}
func (s *subscriber) Options() broker.SubscribeOptions { func (s *subscriber) Options() broker.SubscribeOptions {
return s.opts return s.opts
} }
@ -375,10 +380,26 @@ func (n *natsBroker) Subscribe(topic string, handler broker.Handler, opts ...bro
fn := func(msg *nats.Msg) { fn := func(msg *nats.Msg) {
var m broker.Message var m broker.Message
if err := n.opts.Codec.Unmarshal(msg.Data, &m); err != nil { pub := &publication{t: msg.Subject}
eh := n.opts.ErrorHandler
err := n.opts.Codec.Unmarshal(msg.Data, &m)
pub.err = err
pub.m = &m
if err != nil {
m.Body = msg.Data
log.Error(err)
if eh != nil {
eh(pub)
}
return return
} }
handler(&publication{m: &m, t: msg.Subject}) if err := handler(pub); err != nil {
pub.err = err
log.Error(err)
if eh != nil {
eh(pub)
}
}
} }
var sub *nats.Subscription var sub *nats.Subscription

View File

@ -12,6 +12,11 @@ type Options struct {
Addrs []string Addrs []string
Secure bool Secure bool
Codec codec.Marshaler Codec codec.Marshaler
// Handler executed when error happens in broker mesage
// processing
ErrorHandler Handler
TLSConfig *tls.Config TLSConfig *tls.Config
// Registry used for clustering // Registry used for clustering
Registry registry.Registry Registry registry.Registry
@ -81,6 +86,14 @@ func DisableAutoAck() SubscribeOption {
} }
} }
// ErrorHandler will catch all broker errors that cant be handled
// in normal way, for example Codec errors
func ErrorHandler(h Handler) Option {
return func(o *Options) {
o.ErrorHandler = h
}
}
// Queue sets the name of the queue to share messages on // Queue sets the name of the queue to share messages on
func Queue(name string) SubscribeOption { func Queue(name string) SubscribeOption {
return func(o *SubscribeOptions) { return func(o *SubscribeOptions) {

View File

@ -17,6 +17,7 @@ type serviceSub struct {
type serviceEvent struct { type serviceEvent struct {
topic string topic string
err error
message *broker.Message message *broker.Message
} }
@ -32,6 +33,10 @@ func (s *serviceEvent) Ack() error {
return nil return nil
} }
func (s *serviceEvent) Error() error {
return s.err
}
func (s *serviceSub) isClosed() bool { func (s *serviceSub) isClosed() bool {
select { select {
case <-s.closed: case <-s.closed:
@ -71,14 +76,14 @@ func (s *serviceSub) run() error {
return err return err
} }
// TODO: handle error p := &serviceEvent{
s.handler(&serviceEvent{
topic: s.topic, topic: s.topic,
message: &broker.Message{ message: &broker.Message{
Header: msg.Header, Header: msg.Header,
Body: msg.Body, Body: msg.Body,
}, },
}) }
p.err = s.handler(p)
} }
} }

View File

@ -7,6 +7,7 @@ import (
// event is a broker event we handle on the server transport // event is a broker event we handle on the server transport
type event struct { type event struct {
err error
message *broker.Message message *broker.Message
} }
@ -19,6 +20,10 @@ func (e *event) Message() *broker.Message {
return e.message return e.message
} }
func (e *event) Error() error {
return e.err
}
func (e *event) Topic() string { func (e *event) Topic() string {
return e.message.Header["Micro-Topic"] return e.message.Header["Micro-Topic"]
} }

View File

@ -163,6 +163,10 @@ func (t *tunEvent) Ack() error {
return nil return nil
} }
func (t *tunEvent) Error() error {
return nil
}
func NewBroker(opts ...broker.Option) broker.Broker { func NewBroker(opts ...broker.Option) broker.Broker {
options := broker.Options{ options := broker.Options{
Context: context.Background(), Context: context.Background(),