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
}
