Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/yertools/event_hub
Event-Hub is a Gleam library that provides simple hubs with publishers and subscribers for event-driven observers. It supports asynchronous message handling and event notifications, decoupling components efficiently. It works on Erlang and JavaScript.
https://github.com/yertools/event_hub
erlang events gleam javascript notifications observer observer-pattern publisher subscriber
Last synced: about 1 month ago
JSON representation
Event-Hub is a Gleam library that provides simple hubs with publishers and subscribers for event-driven observers. It supports asynchronous message handling and event notifications, decoupling components efficiently. It works on Erlang and JavaScript.
- Host: GitHub
- URL: https://github.com/yertools/event_hub
- Owner: yerTools
- License: mit
- Created: 2024-05-19T20:29:03.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2024-05-22T06:09:31.000Z (6 months ago)
- Last Synced: 2024-05-22T07:27:14.674Z (6 months ago)
- Topics: erlang, events, gleam, javascript, notifications, observer, observer-pattern, publisher, subscriber
- Language: Gleam
- Homepage: https://hexdocs.pm/event_hub/index.html
- Size: 69.3 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Event-Hub
[![Package Version](https://img.shields.io/hexpm/v/event_hub)](https://hex.pm/packages/event_hub)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/event_hub/)Event-Hub is a Gleam library that provides simple hubs with publishers and
subscribers for event-driven observers. It supports asynchronous message
handling and event notifications, decoupling components efficiently. It works on
Erlang and JavaScript.---
Further documentation can be found at .
- [event_hub](https://hexdocs.pm/event_hub/event_hub.html)
- [event_hub/filtered](https://hexdocs.pm/event_hub/event_hub/filtered.html)
- [event_hub/reactive](https://hexdocs.pm/event_hub/event_hub/reactive.html)
- [event_hub/stateful](https://hexdocs.pm/event_hub/event_hub/stateful.html)
- [event_hub/topic](https://hexdocs.pm/event_hub/event_hub/topic.html)## Try it yourself!
```sh
gleam add event_hub
```## Examples
### Imports:
The following imports where used for the examples:
```gleam
import gleam/int
import gleam/io
import event_hub
import event_hub/filtered
import event_hub/reactive
import event_hub/stateful
import event_hub/topic
```### Simple Observer
A simple observer implementation. This example demonstrates the basic usage of
the Event-Hub library. It is an easy way to use publishers and subscribers to
handle events.```gleam
fn simple_observer() {
// Creates a new hub for distributing events.
use hub <- event_hub.new()// Notifies all subscribers of the hub that an event has occurred.
event_hub.notify(hub, 1)// You can forward the hub to other functions or components.
{
// Using syntactic sugar for handling the callback.
use value <- event_hub.subscribe(hub)// This function gets called when the hub receives an event.
io.println("[1] | Received an event with value: " <> int.to_string(value))
}// You can also subscribe using a normal callback function.
// This also returns an unsubscribe function.
let unsubscribe =
event_hub.subscribe(hub, fn(value) {
io.println("[2] | Received an event with value: " <> int.to_string(value))
})// Notifies all subscribers of the hub that an event has occurred with the value `2`.
// These notifications occur in parallel but notify waits for all of them to complete.
event_hub.notify(hub, 2)// Unsubscribe if you no longer need to receive events.
unsubscribe()// Notify again to demonstrate that the unsubscribe function works.
event_hub.notify(hub, 3)
}
```#### Output:
> [1] | Received an event with value: 2
> [2] | Received an event with value: 2
> [1] | Received an event with value: 3### Simple Observer with State
A simple stateful observer implementation. This is like the previous example,
but it uses a stateful event_hub.```gleam
fn simple_observer_with_state() {
// Creates a new hub for distributing events with an initial state.
use hub <- stateful.new("initial state")// Gets the current state.
let current_state = stateful.state(hub)
io.println("Current state: " <> current_state)// Notifies all subscribers of the hub that an event has occurred.
stateful.notify(hub, "test value")// See that the state has changed.
let current_state = stateful.state(hub)
io.println("Current state: " <> current_state)// You can forward the hub to other functions or components.
{
// Using syntactic sugar for handling the callback.
// With the second argument, you can specify whether the callback should be called with the current state.
use value <- stateful.subscribe(hub, True)// This function gets called when the hub receives an event.
// In this case, it prints the current state because the second argument was `True`.
io.println("[1] | Received an event with value: " <> value)
}// You can also subscribe using a normal callback function.
// This also returns a tuple with the current state and an unsubscribe function.
// The second argument specifies that the callback should not be called with the current state.
let #(current_state, unsubscribe) =
stateful.subscribe(hub, False, fn(value) {
io.println("[2] | Received an event with value: " <> value)
})// See that the state is still the same.
io.println("Current state: " <> current_state)// Notifies all subscribers of the hub that an event has occurred with the value `"third event"`.
// These notifications occur in parallel but notify waits for all of them to complete.
stateful.notify(hub, "third event")// Unsubscribe if you no longer need to receive events.
unsubscribe()// Notify again to demonstrate that the unsubscribe function works.
stateful.notify(hub, "last one")
}
```#### Output:
> Current state: initial state
> Current state: test value
> [1] | Received an event with value: test val
> Current state: test value
> [1] | Received an event with value: third ev
> [2] | Received an event with value: third ev
> [1] | Received an event with value: last one### Reactive Observer
A simple reactive observer implementation. This can be used to broadcast things
that constantly change like the current time to clients. Another use case would
be to broadcast database updates to listeners.```gleam
fn reactive_observer() {
// This is a mockup of the current time function.
// In a real application, you would use a real time function.
let now = fn() { "2024-05-21T16:30:00Z" }// Creates a new hub for distributing events with a current time function.
use time_hub <- reactive.new(now)// Subscribes to the hub to get notified when the current time changes.
let unsubscribe_a =
reactive.subscribe(time_hub, fn(value) {
io.println("[A] | Current time: " <> value)
})// This is another subscription to the hub.
let unsubscribe_b =
reactive.subscribe(time_hub, fn(value) {
io.println("[B] | Current time: " <> value)
})// Just another client.
let unsubscribe_c =
reactive.subscribe(time_hub, fn(value) {
io.println("[C] | Current time: " <> value)
})// Notifies all subscribers of the hub that the current time has changed.
// This will call the provided function when the hub was created and broadcast the return value.
reactive.notify(time_hub)// Unsubscribes from the hub.
unsubscribe_b()// Notifies all subscribers again.
// If a real-time function is used, the current time will be updated.
reactive.notify(time_hub)// Unsubscribe all subscribers.
unsubscribe_c()
unsubscribe_a()
}
```#### Output:
> [A] | Current time: 2024-05-21T16:30:00Z
> [B] | Current time: 2024-05-21T16:30:00Z
> [C] | Current time: 2024-05-21T16:30:00Z
> [A] | Current time: 2024-05-21T16:30:00Z
> [C] | Current time: 2024-05-21T16:30:00Z### Single topic-based Observer
A simple topic-based observer implementation. Topics can be used to organize and
filter events.```gleam
fn single_topic() {
use hub <- topic.new()// Creates a listener for the topics `"a"`, `"ab"` and `"*"`.
let unsubscribe_a =
topic.subscribe(hub, ["a", "ab", "*"], fn(value) {
io.println("[A] | Received an event with value: " <> value)
})// Creates a listener for the topics `"b"`, `"ab"` and `"*"`.
let unsubscribe_b =
topic.subscribe(hub, ["b", "ab", "*"], fn(value) {
io.println("[B] | Received an event with value: " <> value)
})// Creates a listener for the topics `"c"` and `"*"`.
let unsubscribe_c =
topic.subscribe(hub, ["c", "*"], fn(value) {
io.println("[C] | Received an event with value: " <> value)
})// Notifies listeners with the topics `"a"` and `"c"`.
topic.notify(hub, ["a", "c"], "Hello A and C!")// Notifies listeners with the topic `"*"`.
topic.notify(hub, ["*"], "Hello all!")// Notifies listeners with the topic `"ab"`.
topic.notify(hub, ["ab"], "Hello AB!")// Notifies listeners with the topics `"a"`, `"ab"`, `"b"`, `"c"` and `"*"`.
topic.notify(hub, ["a", "ab", "b", "c", "*"], "Hello A, AB, B, C, and all!")// Unsubscribe all listeners.
unsubscribe_a()
unsubscribe_b()
unsubscribe_c()
}
```#### Output:
> [A] | Received an event with value: Hello A and C!
> [C] | Received an event with value: Hello A and C!
> [A] | Received an event with value: Hello all!
> [B] | Received an event with value: Hello all!
> [C] | Received an event with value: Hello all!
> [A] | Received an event with value: Hello AB!
> [B] | Received an event with value: Hello AB!
> [A] | Received an event with value: Hello A, AB, B, C, and all!
> [B] | Received an event with value: Hello A, AB, B, C, and all!
> [C] | Received an event with value: Hello A, AB, B, C, and all!### Multiple topic-based Observer
Example of using multiple topics. This can be used for advanced filtering and
grouping of events. A possible example would be to propagate database changes to
listeners. In this case, the first topic would be the table name and the second
topics could be the column names.```gleam
fn multiple_topics() {
use hub <- topic.new2()// Creates a listener for the `"user"` table and the columns `"name"` and `"age"`.
let unsubscribe_user_name_age =
topic.subscribe2(hub, ["user"], ["name", "age", "*"], fn(value) {
io.println("[User: name, age] | Received an event with value: " <> value)
})// Creates a listener for the `"user"` table and the columns `"name"`, `"age"` and `"email"`.
let unsubscribe_user_details =
topic.subscribe2(hub, ["user"], ["name", "age", "email", "*"], fn(value) {
io.println(
"[User: name, age, email] | Received an event with value: " <> value,
)
})// Update the user name
topic.notify2(hub, ["user"], ["name"], "John Doe")// Update the user email
topic.notify2(hub, ["user"], ["email"], "[email protected]")// Add a new user
topic.notify2(hub, ["user"], ["*"], "Hello World!")unsubscribe_user_name_age()
unsubscribe_user_details()
}
```#### Output:
> [User: name, age] | Received an event with value: John Doe
> [User: name, age, email] | Received an event with value: John Doe
> [User: name, age, email] | Received an event with value:
> [email protected]
> [User: name, age] | Received an event with value: Hello World!
> [User: name, age, email] | Received an event with value: Hello World!### Filtered Observer
This example demonstrates the usage of the filtered event_hub. It is an easy way
to filter events based on a list of topics. They work in a similar way, but you
can use generics to filter by any type.```gleam
fn filtered_observer() {
use hub <- filtered.new3()let unsubscribe_a =
filtered.subscribe3(hub, [0, 1], ["A", "*"], [Ok(Nil)], fn(value) {
io.println("[A] | Received an event with value: " <> value)
})let unsubscribe_b =
filtered.subscribe3(hub, [0, 2], ["B", "*"], [Ok(Nil)], fn(value) {
io.println("[B] | Received an event with value: " <> value)
})// This should notify all subscribers.
filtered.notify3(hub, [0], ["*"], [Ok(Nil)], "Hello all!")// This should notify only subscriber A.
filtered.notify3(hub, [1], ["A", "*"], [Ok(Nil)], "Hello A")// This should notify only subscriber B.
filtered.notify3(hub, [0, 1, 2], ["B"], [Ok(Nil)], "Hello B")// This should notify none.
filtered.notify3(hub, [0, 1, 2], ["A", "B", "*"], [Error(Nil)], "Hello C")unsubscribe_a()
unsubscribe_b()
}
```#### Output:
> [A] | Received an event with value: Hello all!
> [B] | Received an event with value: Hello all!
> [A] | Received an event with value: Hello A
> [B] | Received an event with value: Hello B