/* Package queue provides implementations of server-side queues. */ package queue import ( "github.com/go-stomp/stomp/v3/frame" "github.com/go-stomp/stomp/v3/server/client" ) // Queue for storing message frames. type Queue struct { destination string qstore Storage subs *client.SubscriptionList } // Create a new queue -- called from the queue manager only. func newQueue(destination string, qstore Storage) *Queue { return &Queue{ destination: destination, qstore: qstore, subs: client.NewSubscriptionList(), } } // Add a subscription to a queue. The subscription is removed // whenever a frame is sent to the subscription and needs to // be re-added when the subscription decides that the message // has been received by the client. func (q *Queue) Subscribe(sub *client.Subscription) error { // see if there is a frame available for this subscription f, err := q.qstore.Dequeue(sub.Destination()) if err != nil { return err } if f == nil { // no frame available, so add to the subscription list q.subs.Add(sub) } else { // a frame is available, so send straight away without // adding the subscription to the list sub.SendQueueFrame(f) } return nil } // Unsubscribe a subscription. func (q *Queue) Unsubscribe(sub *client.Subscription) { q.subs.Remove(sub) } // Send a message to the queue. If a subscription is available // to receive the message, it is sent to the subscription without // making it to the queue. Otherwise, the message is queued until // a message is available. func (q *Queue) Enqueue(f *frame.Frame) error { // find a subscription ready to receive the frame sub := q.subs.Get() if sub == nil { // no subscription available, add to the queue return q.qstore.Enqueue(q.destination, f) } else { // subscription is available, send it now without adding to queue sub.SendQueueFrame(f) } return nil } // Send a message to the front of the queue, probably because it // failed to be sent to a client. If a subscription is available // to receive the message, it is sent to the subscription without // making it to the queue. Otherwise, the message is queued until // a message is available. func (q *Queue) Requeue(f *frame.Frame) error { // find a subscription ready to receive the frame sub := q.subs.Get() if sub == nil { // no subscription available, add to the queue return q.qstore.Requeue(q.destination, f) } else { // subscription is available, send it now without adding to queue sub.SendQueueFrame(f) } return nil }