awesome-patterns/messaging/publish_subscribe.md

77 lines
1.8 KiB
Markdown
Raw Normal View History

2016-04-12 06:11:51 +03:00
Publish & Subscribe Messaging Pattern
============
Publish-Subscribe is a messaging pattern used to communicate messages between
different components without these components knowing anything about each other's identity.
It is similar to the Observer behavioral design pattern.
The fundamental design principals of both Observer and Publish-Subscribe is the decoupling of
those interested in being informed about `Event Messages` from the informer (Observers or Publishers).
Meaning that you don't have to program the messages to be sent directly to specific receivers.
To accomplish this, an intermediary, called a "message broker" or "event bus",
receives published messages, and then routes them on to subscribers.
2020-09-28 08:04:32 +03:00
There are three components **messages**, **topics**, **subscriptions**.
2016-04-12 06:11:51 +03:00
```go
type Message struct {
// Contents
}
type Subscription struct {
2020-09-28 08:04:32 +03:00
closed bool
inbox chan Message
2016-04-12 06:11:51 +03:00
}
2020-09-28 08:04:32 +03:00
func (s *Subscription) Next() (Message, error) {
if s.closed {
return Message{}, errors.New("subscription closed")
2016-04-12 06:11:51 +03:00
}
2020-09-28 08:04:32 +03:00
m, ok := <-s.inbox
if !ok {
return Message{}, errors.New("subscription closed")
}
return m, nil
}
2016-04-12 06:11:51 +03:00
2020-09-28 08:04:32 +03:00
func (s *Subscription) Unsubscribe(Subscription) error {
s.closed = true
close(s.inbox)
2016-04-12 06:11:51 +03:00
}
```
```go
type Topic struct {
2020-09-28 08:04:32 +03:00
Subscribers []Subscription
2016-04-12 06:11:51 +03:00
MessageHistory []Message
}
2020-09-28 08:04:32 +03:00
func (t *Topic) Subscribe() (Subscription) {
return Subscription{inbox: make(chan Message)}
2016-04-12 06:11:51 +03:00
}
2020-09-28 08:04:32 +03:00
func (t *Topic) Publish(msg Message) error {
for _, sub := range t.Subscribers {
if sub.closed {
continue
}
go func() {
sub.inbox <- msg
}()
}
2016-04-12 06:11:51 +03:00
2020-09-28 08:04:32 +03:00
return nil
2016-04-12 06:11:51 +03:00
}
```
Improvements
============
Events can be published in a parallel fashion by utilizing stackless goroutines.
Performance can be improved by dealing with straggler subscribers
by using a buffered inbox and you stop sending events once the inbox is full.