Files
2026-09-15 21:27:46 +05:00

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)
}