Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/teivah/broadcast
Notification broadcaster library
https://github.com/teivah/broadcast
channels concurrency go golang goroutine goroutines library notifications parallelism publish-subscribe
Last synced: 9 days ago
JSON representation
Notification broadcaster library
- Host: GitHub
- URL: https://github.com/teivah/broadcast
- Owner: teivah
- License: apache-2.0
- Created: 2021-10-14T19:55:37.000Z (about 3 years ago)
- Default Branch: master
- Last Pushed: 2022-05-05T07:55:07.000Z (over 2 years ago)
- Last Synced: 2024-06-18T15:33:02.505Z (5 months ago)
- Topics: channels, concurrency, go, golang, goroutine, goroutines, library, notifications, parallelism, publish-subscribe
- Language: Go
- Homepage:
- Size: 185 KB
- Stars: 148
- Watchers: 3
- Forks: 8
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# broadcast
![CI](https://github.com/teivah/broadcast/actions/workflows/ci.yml/badge.svg)
[![Go Report Card](https://goreportcard.com/badge/github.com/teivah/broadcast)](https://goreportcard.com/report/github.com/teivah/broadcast)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):
```go
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:
````go
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 guaranteedOn the `Listener` side, we can access the internal channel using `Ch`:
```go
<-list.Ch() // Wait on a notification
```We can close a `Listener` and a `Relay` using `Close`:
```go
list.Close()
relay.Close()
```Closing a `Relay` and `Listener`s can be done concurrently in a safe manner.
### Example
```go
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
```