snapshot of https://github.com/ThreeDotsLabs/watermill.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
master / ci (push) Failing after 0s
Some checks failed
master / ci (push) Failing after 0s
This commit is contained in:
151
_examples/real-world-examples/consumer-groups/api/http.go
Normal file
151
_examples/real-world-examples/consumer-groups/api/http.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/ThreeDotsLabs/watermill"
|
||||
watermillHTTP "github.com/ThreeDotsLabs/watermill-http/pkg/http"
|
||||
"github.com/ThreeDotsLabs/watermill-routing-example/server/common"
|
||||
"github.com/ThreeDotsLabs/watermill/message"
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
storage *storage
|
||||
|
||||
subscriber message.Subscriber
|
||||
publisher message.Publisher
|
||||
logger watermill.LoggerAdapter
|
||||
|
||||
lastIDs map[string]int
|
||||
}
|
||||
|
||||
func (h Handler) Mux() *chi.Mux {
|
||||
r := chi.NewRouter()
|
||||
|
||||
fileServer(r, "/", http.Dir("./public"))
|
||||
|
||||
sseRouter, err := watermillHTTP.NewSSERouter(
|
||||
watermillHTTP.SSERouterConfig{
|
||||
UpstreamSubscriber: h.subscriber,
|
||||
},
|
||||
h.logger,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
messagesHandler := sseRouter.AddHandler(common.UpdatesTopic, messagesStream{
|
||||
logger: h.logger,
|
||||
storage: h.storage,
|
||||
})
|
||||
|
||||
r.Route("/api", func(r chi.Router) {
|
||||
r.Use(requestIDMiddleware)
|
||||
r.Get("/messages", messagesHandler)
|
||||
r.Post("/messages/{topic}", h.SendMessage)
|
||||
})
|
||||
|
||||
go func() {
|
||||
err = sseRouter.Run(context.Background())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
<-sseRouter.Running()
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (h Handler) SendMessage(w http.ResponseWriter, r *http.Request) {
|
||||
topic := chi.URLParam(r, "topic")
|
||||
|
||||
h.lastIDs[topic]++
|
||||
|
||||
msgID := fmt.Sprintf("%v", h.lastIDs[topic])
|
||||
|
||||
event := common.UserSignedUp{
|
||||
UserID: watermill.NewUUID(),
|
||||
Consents: common.Consents{
|
||||
Marketing: true,
|
||||
News: true,
|
||||
},
|
||||
}
|
||||
|
||||
payload, err := json.Marshal(event)
|
||||
if err != nil {
|
||||
logAndWriteError(h.logger, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
msg := message.NewMessage(msgID, payload)
|
||||
msg.Metadata.Set("name", "UserSignedUp")
|
||||
|
||||
err = h.publisher.Publish(topic, msg)
|
||||
if err != nil {
|
||||
logAndWriteError(h.logger, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(204)
|
||||
}
|
||||
|
||||
type messagesStream struct {
|
||||
storage *storage
|
||||
logger watermill.LoggerAdapter
|
||||
}
|
||||
|
||||
func (p messagesStream) GetResponse(w http.ResponseWriter, r *http.Request) (response interface{}, ok bool) {
|
||||
reqID := r.Context().Value("request_id").(string)
|
||||
messages := p.storage.PopAll(reqID)
|
||||
return messages, true
|
||||
}
|
||||
|
||||
func (p messagesStream) Validate(r *http.Request, msg *message.Message) (ok bool) {
|
||||
var payload common.MessageReceived
|
||||
err := json.Unmarshal(msg.Payload, &payload)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
p.storage.Append(payload)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func fileServer(r chi.Router, path string, root http.FileSystem) {
|
||||
if strings.ContainsAny(path, "{}*") {
|
||||
panic("FileServer does not permit URL parameters.")
|
||||
}
|
||||
|
||||
fs := http.StripPrefix(path, http.FileServer(root))
|
||||
|
||||
if path != "/" && path[len(path)-1] != '/' {
|
||||
r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP)
|
||||
path += "/"
|
||||
}
|
||||
path += "*"
|
||||
|
||||
r.Get(path, func(w http.ResponseWriter, r *http.Request) {
|
||||
fs.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func logAndWriteError(logger watermill.LoggerAdapter, w http.ResponseWriter, err error) {
|
||||
logger.Error("Error", err, nil)
|
||||
w.WriteHeader(500)
|
||||
}
|
||||
|
||||
func requestIDMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
requestID := watermill.NewUUID()
|
||||
ctx = context.WithValue(ctx, "request_id", requestID)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user