mirror of
https://github.com/kemko/nomad.git
synced 2026-01-07 10:55:42 +03:00
are removed from the event buffer. Wire up event buffer size config, use pointers for structs.Events instead of copying.
99 lines
2.1 KiB
Go
99 lines
2.1 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
// Events is a set of events for a corresponding index. Events returned for the
|
|
// index depend on which topics are subscribed to when a request is made.
|
|
type Events struct {
|
|
Index uint64
|
|
Events []Event
|
|
Err error
|
|
}
|
|
|
|
// Topic is an event Topic
|
|
type Topic string
|
|
|
|
// Event holds information related to an event that occurred in Nomad.
|
|
// The Payload is a hydrated object related to the Topic
|
|
type Event struct {
|
|
Topic Topic
|
|
Type string
|
|
Key string
|
|
FilterKeys []string
|
|
Index uint64
|
|
Payload map[string]interface{}
|
|
}
|
|
|
|
// IsHeartbeat specifies if the event is an empty heartbeat used to
|
|
// keep a connection alive.
|
|
func (e *Events) IsHeartbeat() bool {
|
|
return e.Index == 0 && len(e.Events) == 0
|
|
}
|
|
|
|
// EventStream is used to stream events from Nomad
|
|
type EventStream struct {
|
|
client *Client
|
|
}
|
|
|
|
// EventStream returns a handle to the Events endpoint
|
|
func (c *Client) EventStream() *EventStream {
|
|
return &EventStream{client: c}
|
|
}
|
|
|
|
// Stream establishes a new subscription to Nomad's event stream and streams
|
|
// results back to the returned channel.
|
|
func (e *EventStream) Stream(ctx context.Context, topics map[Topic][]string, index uint64, q *QueryOptions) (<-chan *Events, error) {
|
|
|
|
r, err := e.client.newRequest("GET", "/v1/event/stream")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r.setQueryOptions(q)
|
|
|
|
// Build topic query params
|
|
for topic, keys := range topics {
|
|
for _, k := range keys {
|
|
r.params.Add("topic", fmt.Sprintf("%s:%s", topic, k))
|
|
}
|
|
}
|
|
|
|
_, resp, err := requireOK(e.client.doRequest(r))
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
eventsCh := make(chan *Events, 10)
|
|
go func() {
|
|
defer resp.Body.Close()
|
|
defer close(eventsCh)
|
|
|
|
dec := json.NewDecoder(resp.Body)
|
|
|
|
for ctx.Err() == nil {
|
|
// Decode next newline delimited json of events
|
|
var events Events
|
|
if err := dec.Decode(&events); err != nil {
|
|
// set error and fallthrough to
|
|
// select eventsCh
|
|
events = Events{Err: err}
|
|
}
|
|
if events.IsHeartbeat() {
|
|
continue
|
|
}
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case eventsCh <- &events:
|
|
}
|
|
}
|
|
}()
|
|
|
|
return eventsCh, nil
|
|
}
|