• Stars
    star
    152
  • Rank 244,685 (Top 5 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created about 3 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Notification broadcaster library

broadcast

CI Go Report Card

Notification broadcaster in Go

What?

broadcast is a library that allows sending repeated notifications to multiple goroutines with guaranteed delivery and user defined types.

Why?

Why not Channels?

The standard way to handle notifications is via a chan struct{}. However, sending a message to a channel is received by a single goroutine.

The only operation that is broadcast to multiple goroutines is a channel closure. Yet, if the channel is closed, there's no way to send a message again.

Repeated notifications to multiple goroutines

Guaranteed delivery

Why not sync.Cond?

sync.Cond is the standard solution based on condition variables to set up containers of goroutines waiting for a specific condition.

There's one caveat to keep in mind, though: the Broadcast() method doesn't guarantee that a goroutine will receive the notification. Indeed, the notification will be lost if the listener goroutine isn't waiting on the Wait() method.

Repeated notifications to multiple goroutines

Guaranteed delivery

How?

Step by Step

First, we need to create a Relay for a message type (empty struct in this case):

relay := broadcast.NewRelay[struct{}]()

Once a Relay is created, we can create a new listener using the Listener method. As the broadcast library relies internally on channels, it accepts a capacity:

list := relay.Listener(1) // Create a new listener based on a channel with a one capacity

A Relay can send a notification in three different manners:

  • Notify: block until a notification is sent to all the listeners
  • NotifyCtx: send a notification to all listeners unless the provided context times out or is canceled
  • Broadcast: send a notification to all listeners in a non-blocking manner; delivery isn't guaranteed

On the Listener side, we can access the internal channel using Ch:

<-list.Ch() // Wait on a notification

We can close a Listener and a Relay using Close:

list.Close() 
relay.Close()

Closing a Relay and Listeners can be done concurrently in a safe manner.

Example

type msg string
const (
    msgA msg = "A"
    msgB     = "B"
    msgC     = "C"
)

relay := broadcast.NewRelay[msg]() // Create a relay for msg values
defer relay.Close()

// Listener goroutines
for i := 0; i < 2; i++ {
    go func(i int) {
        l := relay.Listener(1)  // Create a listener with a buffer capacity of 1
        for n := range l.Ch() { // Ranges over notifications
            fmt.Printf("listener %d has received a notification: %v\n", i, n)
        }
    }(i)
}

// Notifiers
time.Sleep(time.Second)
relay.Notify(msgA)                                     // Send notification with guaranteed delivery
ctx, _ := context.WithTimeout(context.Background(), 0) // Context with immediate timeout
relay.NotifyCtx(ctx, msgB)                             // Send notification respecting context cancellation
time.Sleep(time.Second)                                // Allow time for previous messages to be processed
relay.Broadcast(msgC)                                  // Send notification without guaranteed delivery
time.Sleep(time.Second)                                // Allow time for previous messages to be processed

More Repositories

1

100-go-mistakes

📖 100 Go Mistakes and How to Avoid Them
Go
6,771
star
2

algodeck

An Open-Source Collection of 200+ Flash Cards to Help You Preparing Your Algorithms & Data Structures Interview 💯
5,600
star
3

sre-roadmap

An Opinionated Roadmap to Become an SRE (Concepts > Tools)
416
star
4

designdeck

An Open-Source Collection of 230+ Flash Cards to Help You Succeed in Your System Design Interview and More 💯
328
star
5

gosiris

An actor framework for Go
Go
252
star
6

golang-good-code-bad-code

Go
160
star
7

gossip-glomers

My solutions to the Glomers Challenge: a series of distributed systems challenges.
Go
108
star
8

bitvector

Static bit vector structures library
Go
73
star
9

onecontext

Set of Go context's utilities.
Go
51
star
10

advent-of-code

🎄 My solutions to the Advents of Code, from 2015 to 2023 (450 🌟)
Go
50
star
11

go-lfu

A Go library for handling LFU cache operations in O(1)
Go
40
star
12

goptional

A lightweight library to provide a container for optional values in golang
Go
32
star
13

majorana

A RISC-V virtual processor, written in Go.
Go
22
star
14

ettore

A RISC-V virtual processor, written in Rust.
Rust
19
star
15

talks

My public talks
10
star
16

TIBreview

Quality code review for TIBCO BusinessWorks 6
Java
9
star
17

vertx-tutorial

Vert.x tutorial
Java
9
star
18

golang-parallel-mergesort

Go
8
star
19

tourniquet

gRPC client-side load balancer
Go
8
star
20

go-cpu-caches

Assembly
7
star
21

multilock

A Go Library to Efficiently Store a Set of Mutex or RWMutex
Go
7
star
22

disruptor-demo

Java
6
star
23

rust-cheatsheet

Rust Language Cheat Sheet
Rust
6
star
24

franz

A collection of Kafka utility tools (load testing, replication)
Rust
6
star
25

reactiveWM

A reactive framework for webMethods extending standard multithreading capabilties
Java
5
star
26

generics

A collection of Go generics utilities.
Go
5
star
27

spark-hdfs-helloworld

Java
5
star
28

resequencer

Resequencer library
Go
4
star
29

parallel-mergesort

Java
4
star
30

awesome-cs

A Curated List of Awesome Computer Science Resources
3
star
31

go-bbl

Brown Bag Lunch on the Go programming language
Go
2
star
32

flogomicroservice

Example of a Flogo microservice exposing a REST API
2
star
33

docker-hadoop

Dockerfile
2
star
34

teivah

1
star