Documentation
¶
Overview ¶
Package sse streams server-sent events (text/event-stream).
return sse.Serve(w, r, func(s *sse.Stream) error {
return s.Send("message", "<li>new post</li>")
})
Serve flushes every event, sends heartbeat comments, lifts the server's write timeout for the stream and ends when the client disconnects, the callback returns or the server shuts down. A Hub fans events out to many streams, in memory or through a Broker (drivers/redis) across instances.
See https://github.com/AlexGalhardo/vukem/blob/main/docs/frontend.md.
Example ¶
package main
import (
"context"
"net/http"
"github.com/AlexGalhardo/vukem/sse"
)
func main() {
hub := sse.NewHub(nil) // or sse.NewHub(redisClient) across instances
http.HandleFunc("GET /events", func(w http.ResponseWriter, r *http.Request) {
_ = sse.Serve(w, r, func(s *sse.Stream) error { return hub.Stream(s, "posts") })
})
// Elsewhere, e.g. after creating a post:
_ = hub.Publish(context.Background(), "posts", sse.Event{Event: "created", Data: "<li>New post</li>"})
}
Output:
Index ¶
Examples ¶
Constants ¶
const DefaultHeartbeat = 15 * time.Second
DefaultHeartbeat is the interval of keep-alive comments.
Variables ¶
This section is empty.
Functions ¶
func Serve ¶
Serve streams events to the client of r with fn until fn returns, the client goes away or the server shuts down (Stream.Context is then done).
func ShutdownSignal ¶ added in v0.19.0
ShutdownSignal returns the channel installed by WithShutdown, or nil when ctx has none. Other long-lived connections (the WebSocket driver) end on the same signal.
Types ¶
type Broker ¶
type Broker interface {
Publish(ctx context.Context, channel string, payload []byte) error
Subscribe(ctx context.Context, channels ...string) (<-chan []byte, error)
}
Broker carries events between app instances. Two implementations ship with the framework: *redis.Client from drivers/redis (pub/sub) and *postgres.Broker from drivers/postgres (LISTEN/NOTIFY, for an app that has PostgreSQL and no Redis; it refuses a payload over 7999 bytes, the NOTIFY limit). Subscribe must end the subscription and close the returned channel once ctx is done: the Hub cancels it when a topic loses its last local subscriber.
type Event ¶
type Event struct {
// ID becomes the client's Last-Event-ID on reconnect.
ID string `json:"id,omitempty"`
// Event is the event type ("message" when empty).
Event string `json:"event,omitempty"`
// Data is the payload; newlines become several data lines.
Data string `json:"data"`
// Retry tells the client how long to wait before reconnecting.
Retry time.Duration `json:"retry,omitempty"`
}
Event is one server-sent event.
type Hub ¶
type Hub struct {
// contains filtered or unexported fields
}
Hub fans events published on topics out to subscribed streams. Without a Broker it works within one process; with one, every instance receives every event. A topic holds one broker subscription while it has local subscribers and releases it when the last one leaves.
func (*Hub) Close ¶
func (h *Hub) Close()
Close ends every subscription; later subscriptions end immediately.
func (*Hub) Stream ¶
Stream sends the events of topics to s until the client disconnects, the server shuts down or the hub closes.
func (*Hub) Subscribe ¶
Subscribe returns a channel of the events of topics and a function that unsubscribes. The channel closes on unsubscribe, ctx cancellation, Close, or when the subscriber falls too far behind.
func (*Hub) Subscribers ¶
Subscribers reports how many subscribers topic has.
type Stream ¶
type Stream struct {
// contains filtered or unexported fields
}
Stream writes events to one client; it is safe for concurrent use.
func (*Stream) LastEventID ¶
LastEventID is the Last-Event-ID header of a reconnecting client.