44 lines
1.3 KiB
Go
44 lines
1.3 KiB
Go
package push
|
|
|
|
import (
|
|
pushv1 "galaxy/backend/proto/push/v1"
|
|
)
|
|
|
|
// subscription is the per-gateway-instance delivery queue. Each
|
|
// subscription owns a buffered channel; the publisher writes into it
|
|
// without blocking by dropping the oldest queued event when the buffer
|
|
// is full. The done channel is closed by the Service when the
|
|
// subscription is replaced (a new connection arrived for the same
|
|
// gateway_client_id) or when the Service is shutting down.
|
|
type subscription struct {
|
|
clientID string
|
|
ch chan *pushv1.PushEvent
|
|
done chan struct{}
|
|
dropped uint64
|
|
}
|
|
|
|
// deliver enqueues ev into the subscription's buffer. When the buffer
|
|
// is full, the oldest queued event is dropped to make room and the
|
|
// dropped counter increments. The bool reports whether a drop occurred,
|
|
// so the publisher can update its drop metric.
|
|
//
|
|
// The Service holds its mutex while calling deliver, which means at
|
|
// most one publisher writes to ch at a time. The reader goroutine runs
|
|
// independently and only consumes from ch, so the second send below is
|
|
// guaranteed not to block: after evicting the head, the channel has at
|
|
// least one free slot which no other publisher can fill.
|
|
func (s *subscription) deliver(ev *pushv1.PushEvent) bool {
|
|
select {
|
|
case s.ch <- ev:
|
|
return false
|
|
default:
|
|
}
|
|
select {
|
|
case <-s.ch:
|
|
default:
|
|
}
|
|
s.ch <- ev
|
|
s.dropped++
|
|
return true
|
|
}
|