rabbitmq-amqp-go-client/pkg/rabbitmq_amqp/amqp_consumer.go

114 lines
3.0 KiB
Go

package rabbitmq_amqp
import (
"context"
"fmt"
"github.com/Azure/go-amqp"
"github.com/google/uuid"
"sync/atomic"
)
type DeliveryContext struct {
receiver *amqp.Receiver
message *amqp.Message
}
func (dc *DeliveryContext) Message() *amqp.Message {
return dc.message
}
func (dc *DeliveryContext) Accept(ctx context.Context) error {
return dc.receiver.AcceptMessage(ctx, dc.message)
}
func (dc *DeliveryContext) Discard(ctx context.Context, e *amqp.Error) error {
return dc.receiver.RejectMessage(ctx, dc.message, e)
}
func (dc *DeliveryContext) DiscardWithAnnotations(ctx context.Context, annotations amqp.Annotations) error {
if err := validateMessageAnnotations(annotations); err != nil {
return err
}
// copy the rabbitmq annotations to amqp annotations
destination := make(amqp.Annotations)
for keyA, value := range annotations {
destination[keyA] = value
}
return dc.receiver.ModifyMessage(ctx, dc.message, &amqp.ModifyMessageOptions{
DeliveryFailed: true,
UndeliverableHere: true,
Annotations: destination,
})
}
func (dc *DeliveryContext) Requeue(ctx context.Context) error {
return dc.receiver.ReleaseMessage(ctx, dc.message)
}
func (dc *DeliveryContext) RequeueWithAnnotations(ctx context.Context, annotations amqp.Annotations) error {
if err := validateMessageAnnotations(annotations); err != nil {
return err
}
// copy the rabbitmq annotations to amqp annotations
destination := make(amqp.Annotations)
for key, value := range annotations {
destination[key] = value
}
return dc.receiver.ModifyMessage(ctx, dc.message, &amqp.ModifyMessageOptions{
DeliveryFailed: false,
UndeliverableHere: false,
Annotations: destination,
})
}
type Consumer struct {
receiver atomic.Pointer[amqp.Receiver]
connection *AmqpConnection
linkName string
destinationAdd string
id string
}
func (c *Consumer) Id() string {
return c.id
}
func newConsumer(ctx context.Context, connection *AmqpConnection, destinationAdd string, linkName string, args ...string) (*Consumer, error) {
id := fmt.Sprintf("consumer-%s", uuid.New().String())
if len(args) > 0 {
id = args[0]
}
r := &Consumer{connection: connection, linkName: linkName, destinationAdd: destinationAdd, id: id}
connection.entitiesTracker.storeOrReplaceConsumer(r)
err := r.createReceiver(ctx)
if err != nil {
return nil, err
}
return r, nil
}
func (c *Consumer) createReceiver(ctx context.Context) error {
receiver, err := c.connection.session.NewReceiver(ctx, c.destinationAdd, createReceiverLinkOptions(c.destinationAdd, c.linkName, AtLeastOnce))
if err != nil {
return err
}
c.receiver.Swap(receiver)
return nil
}
func (c *Consumer) Receive(ctx context.Context) (*DeliveryContext, error) {
msg, err := c.receiver.Load().Receive(ctx, nil)
if err != nil {
return nil, err
}
return &DeliveryContext{receiver: c.receiver.Load(), message: msg}, nil
}
func (c *Consumer) Close(ctx context.Context) error {
return c.receiver.Load().Close(ctx)
}