hydroxide-push/events/events.go

113 lines
1.7 KiB
Go
Raw Normal View History

2018-01-11 19:17:11 +02:00
package events
import (
"log"
"sync"
"time"
"github.com/emersion/hydroxide/protonmail"
)
2018-01-12 14:20:17 +02:00
const pollInterval = 30 * time.Second
2018-01-11 19:17:11 +02:00
type Receiver struct {
c *protonmail.Client
2018-10-21 13:15:20 +03:00
locker sync.Mutex
channels []chan<- *protonmail.Event
poll chan struct{}
2018-01-11 19:17:11 +02:00
}
func (r *Receiver) receiveEvents() {
2018-01-11 19:17:11 +02:00
t := time.NewTicker(pollInterval)
defer t.Stop()
var last string
for {
event, err := r.c.GetEvent(last)
2018-01-11 19:17:11 +02:00
if err != nil {
log.Println("cannot receive event:", err)
continue
}
last = event.ID
r.locker.Lock()
2018-01-12 14:20:17 +02:00
n := len(r.channels)
2018-01-11 19:17:11 +02:00
for _, ch := range r.channels {
ch <- event
}
r.locker.Unlock()
2018-01-12 14:20:17 +02:00
if n == 0 {
break
}
select {
case <-t.C:
case <-r.poll:
}
2018-01-11 19:17:11 +02:00
}
}
func (r *Receiver) Poll() {
r.poll <- struct{}{}
}
2018-01-11 19:17:11 +02:00
type Manager struct {
receivers map[string]*Receiver
2018-10-21 13:15:20 +03:00
locker sync.Mutex
2018-01-11 19:17:11 +02:00
}
func NewManager() *Manager {
return &Manager{
receivers: make(map[string]*Receiver),
2018-01-11 19:17:11 +02:00
}
}
func (m *Manager) Register(c *protonmail.Client, username string, ch chan<- *protonmail.Event, done <-chan struct{}) *Receiver {
2018-01-11 19:17:11 +02:00
m.locker.Lock()
defer m.locker.Unlock()
2018-01-12 14:20:17 +02:00
r, ok := m.receivers[username]
if ok {
2018-01-11 19:17:11 +02:00
r.locker.Lock()
r.channels = append(r.channels, ch)
r.locker.Unlock()
} else {
r = &Receiver{
2018-10-21 13:15:20 +03:00
c: c,
2018-01-11 19:17:11 +02:00
channels: []chan<- *protonmail.Event{ch},
2018-10-21 13:15:20 +03:00
poll: make(chan struct{}),
2018-01-11 19:17:11 +02:00
}
2018-01-12 14:20:17 +02:00
go func() {
r.receiveEvents()
2018-01-12 14:20:17 +02:00
m.locker.Lock()
delete(m.receivers, username)
m.locker.Unlock()
}()
2018-01-11 19:17:11 +02:00
m.receivers[username] = r
}
2018-01-12 14:20:17 +02:00
if done != nil {
go func() {
<-done
r.locker.Lock()
for i, c := range r.channels {
if c == ch {
r.channels = append(r.channels[:i], r.channels[i+1:]...)
}
}
r.locker.Unlock()
close(ch)
}()
}
return r
2018-01-11 19:17:11 +02:00
}