181 lines
4.0 KiB
Go
181 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"github.com/ThreeDotsLabs/watermill"
|
|
"github.com/ThreeDotsLabs/watermill-nats/pkg/nats"
|
|
"github.com/ThreeDotsLabs/watermill/message"
|
|
"github.com/ThreeDotsLabs/watermill/message/router/middleware"
|
|
"github.com/nats-io/stan.go"
|
|
)
|
|
|
|
const (
|
|
PostCreatedTopic = "post-created"
|
|
PostUpdatedTopic = "post-updated"
|
|
FeedUpdatedTopic = "feed-updated"
|
|
)
|
|
|
|
func SetupMessageRouter(
|
|
feedsStorage FeedsStorage,
|
|
logger watermill.LoggerAdapter,
|
|
) (message.Publisher, message.Subscriber, error) {
|
|
router, err := message.NewRouter(message.RouterConfig{}, logger)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
router.AddMiddleware(middleware.Recoverer)
|
|
|
|
natsURL := stan.NatsURL("nats://nats-streaming:4222")
|
|
pub, err := nats.NewStreamingPublisher(nats.StreamingPublisherConfig{
|
|
ClusterID: "test-cluster",
|
|
ClientID: "publisher",
|
|
StanOptions: []stan.Option{natsURL},
|
|
Marshaler: nats.GobMarshaler{},
|
|
}, logger)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
sub, err := nats.NewStreamingSubscriber(nats.StreamingSubscriberConfig{
|
|
ClusterID: "test-cluster",
|
|
ClientID: "subscriber",
|
|
StanOptions: []stan.Option{natsURL},
|
|
Unmarshaler: nats.GobMarshaler{},
|
|
}, logger)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
router.AddHandler(
|
|
"update-feeds-on-post-created",
|
|
PostCreatedTopic,
|
|
sub,
|
|
FeedUpdatedTopic,
|
|
pub,
|
|
func(msg *message.Message) (messages []*message.Message, err error) {
|
|
defer func() {
|
|
if err == nil {
|
|
logger.Info("Successfully updated feeds on new post created", nil)
|
|
} else {
|
|
logger.Error("Error while updating feeds on new post created", err, nil)
|
|
}
|
|
}()
|
|
|
|
event := PostCreated{}
|
|
err = json.Unmarshal(msg.Payload, &event)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
logger.Info("Adding post", watermill.LogFields{"post": event.Post})
|
|
|
|
if len(event.Post.Tags) > 0 {
|
|
for _, tag := range event.Post.Tags {
|
|
logger.Info("Adding tag", watermill.LogFields{"tag": tag})
|
|
err = feedsStorage.Add(msg.Context(), tag)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
}
|
|
|
|
err = feedsStorage.AppendPost(msg.Context(), event.Post)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return createFeedUpdatedEvents(event.Post.Tags)
|
|
},
|
|
)
|
|
|
|
router.AddHandler(
|
|
"update-feeds-on-post-updated",
|
|
PostUpdatedTopic,
|
|
sub,
|
|
FeedUpdatedTopic,
|
|
pub,
|
|
func(msg *message.Message) (messages []*message.Message, err error) {
|
|
defer func() {
|
|
if err == nil {
|
|
logger.Info("Successfully updated feeds on post updated", nil)
|
|
} else {
|
|
logger.Error("Error while updating feeds on post updated", err, nil)
|
|
}
|
|
}()
|
|
|
|
event := PostUpdated{}
|
|
err = json.Unmarshal(msg.Payload, &event)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, tag := range event.NewPost.Tags {
|
|
logger.Info("Adding tag", watermill.LogFields{"tag": tag})
|
|
err = feedsStorage.Add(msg.Context(), tag)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
err = feedsStorage.UpdatePost(msg.Context(), event.NewPost)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return createFeedUpdatedEvents(append(event.NewPost.Tags, event.OriginalPost.Tags...))
|
|
},
|
|
)
|
|
|
|
go func() {
|
|
err = router.Run(context.Background())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}()
|
|
|
|
<-router.Running()
|
|
|
|
return pub, sub, nil
|
|
}
|
|
|
|
func createFeedUpdatedEvents(tags []string) ([]*message.Message, error) {
|
|
var messages []*message.Message
|
|
|
|
for _, tag := range tags {
|
|
event := FeedUpdated{
|
|
Name: tag,
|
|
OccurredAt: time.Now().UTC(),
|
|
}
|
|
|
|
payload, err := json.Marshal(event)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
msg := message.NewMessage(watermill.NewUUID(), payload)
|
|
|
|
messages = append(messages, msg)
|
|
}
|
|
|
|
return messages, nil
|
|
}
|
|
|
|
type Publisher struct {
|
|
publisher message.Publisher
|
|
}
|
|
|
|
func (p Publisher) Publish(topic string, event interface{}) error {
|
|
payload, err := json.Marshal(event)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
msg := message.NewMessage(watermill.NewUUID(), payload)
|
|
|
|
return p.publisher.Publish(topic, msg)
|
|
}
|