go-micro.dev/v5@v5.12.0/broker/rabbitmq/channel.go (about)

     1  package rabbitmq
     2  
     3  //
     4  // All credit to Mondo
     5  //
     6  
     7  import (
     8  	"errors"
     9  	"sync"
    10  
    11  	"github.com/google/uuid"
    12  	amqp "github.com/rabbitmq/amqp091-go"
    13  )
    14  
    15  type rabbitMQChannel struct {
    16  	uuid           string
    17  	connection     *amqp.Connection
    18  	channel        *amqp.Channel
    19  	confirmPublish chan amqp.Confirmation
    20  	mtx            sync.Mutex
    21  }
    22  
    23  func newRabbitChannel(conn *amqp.Connection, prefetchCount int, prefetchGlobal bool, confirmPublish bool) (*rabbitMQChannel, error) {
    24  	id, err := uuid.NewRandom()
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  	rabbitCh := &rabbitMQChannel{
    29  		uuid:       id.String(),
    30  		connection: conn,
    31  	}
    32  	if err := rabbitCh.Connect(prefetchCount, prefetchGlobal, confirmPublish); err != nil {
    33  		return nil, err
    34  	}
    35  	return rabbitCh, nil
    36  }
    37  
    38  func (r *rabbitMQChannel) Connect(prefetchCount int, prefetchGlobal bool, confirmPublish bool) error {
    39  	var err error
    40  	r.channel, err = r.connection.Channel()
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	err = r.channel.Qos(prefetchCount, 0, prefetchGlobal)
    46  	if err != nil {
    47  		return err
    48  	}
    49  
    50  	if confirmPublish {
    51  		r.confirmPublish = r.channel.NotifyPublish(make(chan amqp.Confirmation, 1))
    52  
    53  		err = r.channel.Confirm(false)
    54  		if err != nil {
    55  			return err
    56  		}
    57  	}
    58  
    59  	return nil
    60  }
    61  
    62  func (r *rabbitMQChannel) Close() error {
    63  	if r.channel == nil {
    64  		return errors.New("Channel is nil")
    65  	}
    66  	return r.channel.Close()
    67  }
    68  
    69  func (r *rabbitMQChannel) Publish(exchange, key string, message amqp.Publishing) error {
    70  	if r.channel == nil {
    71  		return errors.New("Channel is nil")
    72  	}
    73  
    74  	if r.confirmPublish != nil {
    75  		r.mtx.Lock()
    76  		defer r.mtx.Unlock()
    77  	}
    78  
    79  	err := r.channel.Publish(exchange, key, false, false, message)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	if r.confirmPublish != nil {
    85  		confirmation, ok := <-r.confirmPublish
    86  		if !ok {
    87  			return errors.New("Channel closed before could receive confirmation of publish")
    88  		}
    89  
    90  		if !confirmation.Ack {
    91  			return errors.New("Could not publish message, received nack from broker on confirmation")
    92  		}
    93  	}
    94  
    95  	return nil
    96  }
    97  
    98  func (r *rabbitMQChannel) DeclareExchange(ex Exchange) error {
    99  	return r.channel.ExchangeDeclare(
   100  		ex.Name,         // name
   101  		string(ex.Type), // kind
   102  		ex.Durable,      // durable
   103  		false,           // autoDelete
   104  		false,           // internal
   105  		false,           // noWait
   106  		nil,             // args
   107  	)
   108  }
   109  
   110  func (r *rabbitMQChannel) DeclareDurableExchange(ex Exchange) error {
   111  	return r.channel.ExchangeDeclare(
   112  		ex.Name,         // name
   113  		string(ex.Type), // kind
   114  		true,            // durable
   115  		false,           // autoDelete
   116  		false,           // internal
   117  		false,           // noWait
   118  		nil,             // args
   119  	)
   120  }
   121  
   122  func (r *rabbitMQChannel) DeclareQueue(queue string, args amqp.Table) error {
   123  	_, err := r.channel.QueueDeclare(
   124  		queue, // name
   125  		false, // durable
   126  		true,  // autoDelete
   127  		false, // exclusive
   128  		false, // noWait
   129  		args,  // args
   130  	)
   131  	return err
   132  }
   133  
   134  func (r *rabbitMQChannel) DeclareDurableQueue(queue string, args amqp.Table) error {
   135  	_, err := r.channel.QueueDeclare(
   136  		queue, // name
   137  		true,  // durable
   138  		false, // autoDelete
   139  		false, // exclusive
   140  		false, // noWait
   141  		args,  // args
   142  	)
   143  	return err
   144  }
   145  
   146  func (r *rabbitMQChannel) DeclareReplyQueue(queue string) error {
   147  	_, err := r.channel.QueueDeclare(
   148  		queue, // name
   149  		false, // durable
   150  		true,  // autoDelete
   151  		true,  // exclusive
   152  		false, // noWait
   153  		nil,   // args
   154  	)
   155  	return err
   156  }
   157  
   158  func (r *rabbitMQChannel) ConsumeQueue(queue string, autoAck bool) (<-chan amqp.Delivery, error) {
   159  	return r.channel.Consume(
   160  		queue,   // queue
   161  		r.uuid,  // consumer
   162  		autoAck, // autoAck
   163  		false,   // exclusive
   164  		false,   // nolocal
   165  		false,   // nowait
   166  		nil,     // args
   167  	)
   168  }
   169  
   170  func (r *rabbitMQChannel) BindQueue(queue, key, exchange string, args amqp.Table) error {
   171  	return r.channel.QueueBind(
   172  		queue,    // name
   173  		key,      // key
   174  		exchange, // exchange
   175  		false,    // noWait
   176  		args,     // args
   177  	)
   178  }