Skip to content

Latest commit

 

History

History

07_pub_sub

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

📡 Pub/Sub Pattern

🌟 Introduction

The Publish/Subscribe (Pub/Sub) Pattern is a messaging paradigm where publishers send messages without knowing who will receive them, and subscribers receive messages without knowing who sent them. This decouples the producers and consumers of information, making the system more modular and scalable.

  • Publisher: The entity that produces messages.
  • Subscriber: The entity that consumes messages.
  • Broker: The intermediary that facilitates communication between publishers and subscribers (can be implemented as a channel in Go).

🔑 How It Works

  1. Publish Messages: Publishers send messages to a centralized message broker (or directly to subscribers).
  2. Subscribe to Topics: Subscribers express interest in specific topics or message types.
  3. Distribute Messages: The broker delivers messages to all subscribers interested in a topic.

📌 Code Example

Implementing a Pub/Sub system using Go channels.

package main

import (
	"fmt"
	"sync"
	"time"
)

type Broker struct {
	mu          sync.Mutex
	subscribers map[string][]chan string
}

// Create a new Broker
func NewBroker() *Broker {
	return &Broker{
		subscribers: make(map[string][]chan string),
	}
}

// Subscribe to a topic
func (b *Broker) Subscribe(topic string) <-chan string {
	b.mu.Lock()
	defer b.mu.Unlock()

	ch := make(chan string, 1)
	b.subscribers[topic] = append(b.subscribers[topic], ch)
	return ch
}

// Publish a message to a topic
func (b *Broker) Publish(topic, message string) {
	b.mu.Lock()
	defer b.mu.Unlock()

	for _, subscriber := range b.subscribers[topic] {
		subscriber <- message
	}
}

// Close all subscriber channels
func (b *Broker) Close() {
	b.mu.Lock()
	defer b.mu.Unlock()

	for _, subscribers := range b.subscribers {
		for _, subscriber := range subscribers {
			close(subscriber)
		}
	}
}

func main() {
	broker := NewBroker()
	defer broker.Close()

	// Subscribers
	sub1 := broker.Subscribe("news")
	sub2 := broker.Subscribe("news")

	// Publisher
	go func() {
		for i := 1; i <= 3; i++ {
			msg := fmt.Sprintf("Breaking News %d", i)
			broker.Publish("news", msg)
			time.Sleep(1 * time.Second)
		}
	}()

	// Subscribers receive messages
	wg := sync.WaitGroup{}
	wg.Add(2)

	go func() {
		defer wg.Done()
		for msg := range sub1 {
			fmt.Println("Subscriber 1 received:", msg)
		}
	}()

	go func() {
		defer wg.Done()
		for msg := range sub2 {
			fmt.Println("Subscriber 2 received:", msg)
		}
	}()

	wg.Wait()
}

📌 Explanation

  1. Broker:
    • Manages topics and their subscribers.
    • Synchronizes access to its internal state with a sync.Mutex.
  2. Subscribe:
    • Creates a channel for a new subscriber and associates it with the topic.
  3. Publish:
    • Sends messages to all channels subscribed to a specific topic.
  4. Concurrency:
    • Uses goroutines for asynchronous message publishing and receiving.

🎯 Conclusion

The Pub/Sub Pattern enhances modularity and scalability by decoupling message producers and consumers. It's widely used in event-driven systems and real-time applications like chat apps, notifications, and logging systems.