package syncthing import ( "log" "sync" "time" ) // EventHandler is called for each batch of new events. type EventHandler func(events []Event) // EventListener long-polls the Syncthing event API. type EventListener struct { client *Client handler EventHandler sinceID int stopCh chan struct{} wg sync.WaitGroup } // NewEventListener creates a new event listener. func NewEventListener(client *Client, sinceID int, handler EventHandler) *EventListener { return &EventListener{ client: client, handler: handler, sinceID: sinceID, stopCh: make(chan struct{}), } } // Start begins long-polling in a goroutine. func (el *EventListener) Start() { el.wg.Add(1) go el.loop() } // Stop stops the event listener and waits for it to finish. func (el *EventListener) Stop() { close(el.stopCh) el.wg.Wait() } // LastEventID returns the last processed event ID. func (el *EventListener) LastEventID() int { return el.sinceID } func (el *EventListener) loop() { defer el.wg.Done() backoff := time.Second maxBackoff := 30 * time.Second for { select { case <-el.stopCh: return default: } events, err := el.client.Events(el.sinceID, 30) if err != nil { log.Printf("event poll error: %v", err) select { case <-el.stopCh: return case <-time.After(backoff): } backoff *= 2 if backoff > maxBackoff { backoff = maxBackoff } continue } backoff = time.Second if len(events) > 0 { el.sinceID = events[len(events)-1].ID el.handler(events) } } }