sigmal
This is a dead simple signals library for the JavaScript target. It allows long-running processes to communicate. I made it to use on a web server, but it can be used in just about any application.
Example
Here is a minimal example with smol
. Every time a request is made to the say
path, the server emits say
SSE events on the listen
path.
pub fn main() {
let signal = signal.new()
smol.new(handler(_, signal))
|> smol.start
}
pub fn handler(request, signal) {
case request.path_segments(request) {
["say", msg] -> {
signal.send(signal, msg)
smol.send_status(200)
}
["listen"] ->
smol.server_sent_events(Nil, fn(_) {
use msg <- promise.await(signal.receive(signal))
smol.send(Nil, smol.SseEvent(Some("say"), msg, None, None))
})
_ -> smol.send_status(404)
}
|> promise.resolve
}
Usage
Always begin by creating your Signals
. They must be shared in order for communication to work. There is no way to name a Signal
or find one by name.
Signals
are generic over the type of messages they transfer. This means that one Signal
can only deliver one type of message, even across different topics. If you need to listen for multiple types of messages, you can either use multiple Signals
(which is problematic because you can only await a receive
call on one of them at a time), or write a wrapper type:
type Msg1 {
Msg1(..)
}
type Msg2 {
Msg2(..)
}
type MsgWrapper {
Msg1Wrapper(Msg1)
Msg2Wrapper(Msg2)
}
// inside a function
use msg <- promise.await(signal.receive(my_signal))
case msg {
Msg1Wrapper(_) -> ..
Msg2Wrapper(_) -> ..
}
receive_*
calls are resolved immediately after a send_*
call is made to the corresponding topic(s). Messages are not stored or queued, i.e. if a message is not received, it is lost forever. This means that in order for a message to be delivered successfully, receive_*
must be called before send_*
.
There is no way to subscribe to messages from a signal / topic. However, you should be able to replicate this functionality with a recursive async function that repeatedly calls receive_*
.
Notes
Please remember that this is a “dead simple” library. I do not intend to add any more complex functionality to it. However, please do feel free to use my code as a base for writing your own.
I have done very little testing with this library. Bug reports are welcome.