package events import ( "sync" ) // ErrorLevel is the level of the ServerError type ErrorLevel string // Status is the status of an event type Status string // Different ErrorLevels and statuses const ( // ErrorLevel WarningError ErrorLevel = "warning" FatalError ErrorLevel = "fatal" // Statuses OK Status = "ok" Error Status = "error" ) // Event is the base of a message type Event struct { Type string `json:"type"` Status Status `json:"status"` } // ClientMessage represents a message sent by the client type ClientMessage struct { Event Message string `json:"message"` } // ServerEvent represents an event sent to the client type ServerEvent struct { Event Data interface{} `json:"message"` } // ErrorEvent represents an event error type ErrorEvent struct { Level ErrorLevel `json:"level"` Message string `json:"message"` } // ServerError represents an error sent to the client type ServerError struct { Event ErrorEvent `json:"error"` } // Eventer define an interface that any eventer must follow type Eventer interface { Subscribe(func()) Unsubscribe() Launch() Name() string } // Notifier represents the base of any Eventer // Notify implements Subscribe and Unsubscribe methods type Notifier struct { sync.RWMutex subscribed bool done chan struct{} eventStream chan ServerEvent errorStream chan ServerError } // NewNotifier returns a new notifier func NewNotifier(eventStream chan ServerEvent, errorStream chan ServerError) *Notifier { return &Notifier{ eventStream: eventStream, errorStream: errorStream, done: make(chan struct{}), } } // Subscribe subscribes a client on the Notifier func (t *Notifier) Subscribe(launch func()) { t.Lock() defer t.Unlock() // Check if already subscribed if t.subscribed { return } t.subscribed = true go launch() } // Unsubscribe unsubscribes a client from receiving any more events from // the Notifier func (t *Notifier) Unsubscribe() { t.Lock() defer t.Unlock() // Check if already unsubscribed if !t.subscribed { return } t.subscribed = false t.done <- struct{}{} } // Error sends an error into the errorStream channel func (t *Notifier) Error(name string, err error) { t.errorStream <- ServerError{ Event: Event{ Type: name, Status: Error, }, ErrorEvent: ErrorEvent{ Level: WarningError, Message: err.Error(), }, } } // FatalError sends an error into the errorStream channel and tell the client // that the error is fatal, the notifier won't communicate until a new // subscribe func (t *Notifier) FatalError(name string, err error) { t.Lock() defer t.Unlock() t.errorStream <- ServerError{ Event: Event{ Type: name, Status: Error, }, ErrorEvent: ErrorEvent{ Level: FatalError, Message: err.Error(), }, } t.subscribed = false }