···11package messagebroker
2233+// Message represents a message that can be published or consumed
34type Message struct {
45 Topic string `json:"topic"`
56 Data []byte `json:"data"`
+59
pubsub/publisher.go
···11+package pubsub
22+33+import (
44+ "encoding/binary"
55+ "encoding/json"
66+ "fmt"
77+ "net"
88+99+ "github.com/willdot/messagebroker"
1010+ "github.com/willdot/messagebroker/server"
1111+)
1212+1313+// Publisher allows messages to be published to a server
1414+type Publisher struct {
1515+ conn net.Conn
1616+}
1717+1818+// NewPublisher connects to the server at the given address and registers as a publisher
1919+func NewPublisher(addr string) (*Publisher, error) {
2020+ conn, err := net.Dial("tcp", addr)
2121+ if err != nil {
2222+ return nil, fmt.Errorf("failed to dial: %w", err)
2323+ }
2424+2525+ err = binary.Write(conn, binary.BigEndian, server.Publish)
2626+ if err != nil {
2727+ conn.Close()
2828+ return nil, fmt.Errorf("failed to register publish to server: %w", err)
2929+ }
3030+3131+ return &Publisher{
3232+ conn: conn,
3333+ }, nil
3434+}
3535+3636+// Close cleanly shuts down the publisher
3737+func (p *Publisher) Close() error {
3838+ return p.conn.Close()
3939+}
4040+4141+// Publish will publish the given message to the server
4242+func (p *Publisher) PublishMessage(message messagebroker.Message) error {
4343+ b, err := json.Marshal(message)
4444+ if err != nil {
4545+ return fmt.Errorf("failed to marshal message: %w", err)
4646+ }
4747+4848+ err = binary.Write(p.conn, binary.BigEndian, uint32(len(b)))
4949+ if err != nil {
5050+ return fmt.Errorf("failed to write message size to server")
5151+ }
5252+5353+ _, err = p.conn.Write(b)
5454+ if err != nil {
5555+ return fmt.Errorf("failed to publish data to server")
5656+ }
5757+5858+ return nil
5959+}
+4-1
server/server.go
···2121 Publish Action = 3
2222)
23232424+// Server accepts subscribe and publish connections and passes messages around
2425type Server struct {
2526 addr string
2627 lis net.Listener
···2930 topics map[string]topic
3031}
31323333+// New creates and starts a new server
3234func New(ctx context.Context, addr string) (*Server, error) {
3335 lis, err := net.Listen("tcp", addr)
3436 if err != nil {
···4547 return srv, nil
4648}
47495050+// Shutdown will cleanly shutdown the server
4851func (s *Server) Shutdown() error {
4952 return s.lis.Close()
5053}
···231234 t = newTopic(topicName)
232235 }
233236234234- t.subscriptions[peer.addr()] = Subscriber{
237237+ t.subscriptions[peer.addr()] = subscriber{
235238 peer: peer,
236239 currentOffset: 0,
237240 }
···11-package subscriber
11+package pubsub
2233import (
44 "context"
···1313 "github.com/willdot/messagebroker/server"
1414)
15151616+// Subscriber allows subscriptions to a server and the consumption of messages
1617type Subscriber struct {
1718 conn net.Conn
1819}
19202020-func New(addr string) (*Subscriber, error) {
2121+// NewSubscriber will connect to the server at the given address
2222+func NewSubscriber(addr string) (*Subscriber, error) {
2123 conn, err := net.Dial("tcp", addr)
2224 if err != nil {
2325 return nil, fmt.Errorf("failed to dial: %w", err)
···2830 }, nil
2931}
30323333+// Close cleanly shuts down the subscriber
3134func (s *Subscriber) Close() error {
3235 return s.conn.Close()
3336}
34373838+// SubscribeToTopics will subscribe to the provided topics
3539func (s *Subscriber) SubscribeToTopics(topicNames []string) error {
3640 err := binary.Write(s.conn, binary.BigEndian, server.Subscribe)
3741 if err != nil {
···6670 return nil
6771}
68727373+// Consumer allows the consumption of messages. It is thread safe to range over the Msgs channel to consume. If during the consumer
7474+// receiving messages from the server an error occurs, it will be stored in Err
6975type Consumer struct {
7076 Msgs chan messagebroker.Message
7171- Err error
7777+ // TODO: better error handling? Maybe a channel of errors?
7878+ Err error
7279}
73807474-// TODO: maybe buffer the message channel up?
8181+// Consume will create a consumer and start it running in a go routine. You can then use the Msgs channel of the consumer
8282+// to read the messages
7583func (s *Subscriber) Consume(ctx context.Context) *Consumer {
7684 consumer := &Consumer{
7785 Msgs: make(chan messagebroker.Message),