| @ -1,248 +0,0 @@ | |||||
| package rabbitmq | |||||
| import ( | |||||
| amqp "github.com/rabbitmq/amqp091-go" | |||||
| ) | |||||
| // getDefaultConsumeOptions describes the options that will be used when a value isn't provided | |||||
| func getDefaultConsumeOptions(queueName string) ConsumeOptions { | |||||
| return ConsumeOptions{ | |||||
| RabbitConsumerOptions: RabbitConsumerOptions{ | |||||
| Name: "", | |||||
| AutoAck: false, | |||||
| Exclusive: false, | |||||
| NoWait: false, | |||||
| NoLocal: false, | |||||
| Args: Table{}, | |||||
| }, | |||||
| QueueOptions: QueueOptions{ | |||||
| Name: queueName, | |||||
| Durable: false, | |||||
| AutoDelete: false, | |||||
| Exclusive: false, | |||||
| NoWait: false, | |||||
| Passive: false, | |||||
| Args: Table{}, | |||||
| Declare: true, | |||||
| }, | |||||
| ExchangeOptions: ExchangeOptions{ | |||||
| Name: "", | |||||
| Kind: amqp.ExchangeDirect, | |||||
| Durable: false, | |||||
| AutoDelete: false, | |||||
| Internal: false, | |||||
| NoWait: false, | |||||
| Passive: false, | |||||
| Args: Table{}, | |||||
| Declare: true, | |||||
| }, | |||||
| Bindings: []Binding{}, | |||||
| Concurrency: 1, | |||||
| } | |||||
| } | |||||
| func getDefaultBindingOptions() BindingOptions { | |||||
| return BindingOptions{ | |||||
| NoWait: false, | |||||
| Args: Table{}, | |||||
| Declare: true, | |||||
| } | |||||
| } | |||||
| // ConsumeOptions are used to describe how a new consumer will be created. | |||||
| // If QueueOptions is not nil, the options will be used to declare a queue | |||||
| // If ExchangeOptions is not nil, it will be used to declare an exchange | |||||
| // If there are Bindings, the queue will be bound to them | |||||
| type ConsumeOptions struct { | |||||
| RabbitConsumerOptions RabbitConsumerOptions | |||||
| QueueOptions QueueOptions | |||||
| ExchangeOptions ExchangeOptions | |||||
| Bindings []Binding | |||||
| Concurrency int | |||||
| } | |||||
| // RabbitConsumerOptions are used to configure the consumer | |||||
| // on the rabbit server | |||||
| type RabbitConsumerOptions struct { | |||||
| Name string | |||||
| AutoAck bool | |||||
| Exclusive bool | |||||
| NoWait bool | |||||
| NoLocal bool | |||||
| Args Table | |||||
| } | |||||
| // QueueOptions are used to configure a queue. | |||||
| // A passive queue is assumed by RabbitMQ to already exist, and attempting to connect | |||||
| // to a non-existent queue will cause RabbitMQ to throw an exception. | |||||
| type QueueOptions struct { | |||||
| Name string | |||||
| Durable bool | |||||
| AutoDelete bool | |||||
| Exclusive bool | |||||
| NoWait bool | |||||
| Passive bool // if false, a missing queue will be created on the server | |||||
| Args Table | |||||
| Declare bool | |||||
| } | |||||
| // Binding describes the bhinding of a queue to a routing key on an exchange | |||||
| type Binding struct { | |||||
| RoutingKey string | |||||
| BindingOptions | |||||
| } | |||||
| // BindingOptions describes the options a binding can have | |||||
| type BindingOptions struct { | |||||
| NoWait bool | |||||
| Args Table | |||||
| Declare bool | |||||
| } | |||||
| // WithConsumeOptionsQueueDurable ensures the queue is a durable queue | |||||
| func WithConsumeOptionsQueueDurable(options *ConsumeOptions) { | |||||
| options.QueueOptions.Durable = true | |||||
| } | |||||
| // WithConsumeOptionsQueueAutoDelete ensures the queue is an auto-delete queue | |||||
| func WithConsumeOptionsQueueAutoDelete(options *ConsumeOptions) { | |||||
| options.QueueOptions.AutoDelete = true | |||||
| } | |||||
| // WithConsumeOptionsQueueExclusive ensures the queue is an exclusive queue | |||||
| func WithConsumeOptionsQueueExclusive(options *ConsumeOptions) { | |||||
| options.QueueOptions.Exclusive = true | |||||
| } | |||||
| // WithConsumeOptionsQueueNoWait ensures the queue is a no-wait queue | |||||
| func WithConsumeOptionsQueueNoWait(options *ConsumeOptions) { | |||||
| options.QueueOptions.NoWait = true | |||||
| } | |||||
| // WithConsumeOptionsQueuePassive ensures the queue is a passive queue | |||||
| func WithConsumeOptionsQueuePassive(options *ConsumeOptions) { | |||||
| options.QueueOptions.Passive = true | |||||
| } | |||||
| // WithConsumeOptionsQueueNoDeclare will turn off the declaration of the queue's | |||||
| // existance upon startup | |||||
| func WithConsumeOptionsQueueNoDeclare(options *ConsumeOptions) { | |||||
| options.QueueOptions.Declare = false | |||||
| } | |||||
| // WithConsumeOptionsQueueArgs adds optional args to the queue | |||||
| func WithConsumeOptionsQueueArgs(args Table) func(*ConsumeOptions) { | |||||
| return func(options *ConsumeOptions) { | |||||
| options.QueueOptions.Args = args | |||||
| } | |||||
| } | |||||
| // WithConsumeOptionsExchangeName sets the exchange name | |||||
| func WithConsumeOptionsExchangeName(name string) func(*ConsumeOptions) { | |||||
| return func(options *ConsumeOptions) { | |||||
| options.ExchangeOptions.Name = name | |||||
| } | |||||
| } | |||||
| // WithConsumeOptionsExchangeKind ensures the queue is a durable queue | |||||
| func WithConsumeOptionsExchangeKind(kind string) func(*ConsumeOptions) { | |||||
| return func(options *ConsumeOptions) { | |||||
| options.ExchangeOptions.Kind = kind | |||||
| } | |||||
| } | |||||
| // WithConsumeOptionsExchangeDurable ensures the exchange is a durable exchange | |||||
| func WithConsumeOptionsExchangeDurable(options *ConsumeOptions) { | |||||
| options.ExchangeOptions.Durable = true | |||||
| } | |||||
| // WithConsumeOptionsExchangeAutoDelete ensures the exchange is an auto-delete exchange | |||||
| func WithConsumeOptionsExchangeAutoDelete(options *ConsumeOptions) { | |||||
| options.ExchangeOptions.AutoDelete = true | |||||
| } | |||||
| // WithConsumeOptionsExchangeInternal ensures the exchange is an internal exchange | |||||
| func WithConsumeOptionsExchangeInternal(options *ConsumeOptions) { | |||||
| options.ExchangeOptions.Internal = true | |||||
| } | |||||
| // WithConsumeOptionsExchangeNoWait ensures the exchange is a no-wait exchange | |||||
| func WithConsumeOptionsExchangeNoWait(options *ConsumeOptions) { | |||||
| options.ExchangeOptions.NoWait = true | |||||
| } | |||||
| // WithConsumeOptionsExchangeNoDeclare stops this library from declaring the exchanges existance | |||||
| func WithConsumeOptionsExchangeNoDeclare(options *ConsumeOptions) { | |||||
| options.ExchangeOptions.Declare = false | |||||
| } | |||||
| // WithConsumeOptionsExchangePassive ensures the exchange is a passive exchange | |||||
| func WithConsumeOptionsExchangePassive(options *ConsumeOptions) { | |||||
| options.ExchangeOptions.Passive = true | |||||
| } | |||||
| // WithConsumeOptionsExchangeArgs adds optional args to the exchange | |||||
| func WithConsumeOptionsExchangeArgs(args Table) func(*ConsumeOptions) { | |||||
| return func(options *ConsumeOptions) { | |||||
| options.ExchangeOptions.Args = args | |||||
| } | |||||
| } | |||||
| // WithConsumeOptionsDefaultBinding binds the queue to a routing key with the default binding options | |||||
| func WithConsumeOptionsDefaultBinding(routingKey string) func(*ConsumeOptions) { | |||||
| return func(options *ConsumeOptions) { | |||||
| options.Bindings = append(options.Bindings, Binding{ | |||||
| RoutingKey: routingKey, | |||||
| BindingOptions: getDefaultBindingOptions(), | |||||
| }) | |||||
| } | |||||
| } | |||||
| // WithConsumeOptionsBinding adds a new binding to the queue which allows you to set the binding options | |||||
| // on a per-binding basis. Keep in mind that everything in the BindingOptions struct will default to | |||||
| // the zero value. If you want to declare your bindings for example, be sure to set Declare=true | |||||
| func WithConsumeOptionsBinding(binding Binding) func(*ConsumeOptions) { | |||||
| return func(options *ConsumeOptions) { | |||||
| options.Bindings = append(options.Bindings, binding) | |||||
| } | |||||
| } | |||||
| // WithConsumeOptionsConcurrency returns a function that sets the concurrency, which means that | |||||
| // many goroutines will be spawned to run the provided handler on messages | |||||
| func WithConsumeOptionsConcurrency(concurrency int) func(*ConsumeOptions) { | |||||
| return func(options *ConsumeOptions) { | |||||
| options.Concurrency = concurrency | |||||
| } | |||||
| } | |||||
| // WithConsumeOptionsConsumerName returns a function that sets the name on the server of this consumer | |||||
| // if unset a random name will be given | |||||
| func WithConsumeOptionsConsumerName(consumerName string) func(*ConsumeOptions) { | |||||
| return func(options *ConsumeOptions) { | |||||
| options.RabbitConsumerOptions.Name = consumerName | |||||
| } | |||||
| } | |||||
| // WithConsumeOptionsConsumerAutoAck returns a function that sets the auto acknowledge property on the server of this consumer | |||||
| // if unset the default will be used (false) | |||||
| func WithConsumeOptionsConsumerAutoAck(autoAck bool) func(*ConsumeOptions) { | |||||
| return func(options *ConsumeOptions) { | |||||
| options.RabbitConsumerOptions.AutoAck = autoAck | |||||
| } | |||||
| } | |||||
| // WithConsumeOptionsConsumerExclusive sets the consumer to exclusive, which means | |||||
| // the server will ensure that this is the sole consumer | |||||
| // from this queue. When exclusive is false, the server will fairly distribute | |||||
| // deliveries across multiple consumers. | |||||
| func WithConsumeOptionsConsumerExclusive(options *ConsumeOptions) { | |||||
| options.RabbitConsumerOptions.Exclusive = true | |||||
| } | |||||
| // WithConsumeOptionsConsumerNoWait sets the consumer to nowait, which means | |||||
| // it does not wait for the server to confirm the request and | |||||
| // immediately begin deliveries. If it is not possible to consume, a channel | |||||
| // exception will be raised and the channel will be closed. | |||||
| func WithConsumeOptionsConsumerNoWait(options *ConsumeOptions) { | |||||
| options.RabbitConsumerOptions.NoWait = true | |||||
| } | |||||
| @ -0,0 +1,264 @@ | |||||
| package rabbitmq | |||||
| import ( | |||||
| amqp "github.com/rabbitmq/amqp091-go" | |||||
| "github.com/wagslane/go-rabbitmq/internal/logger" | |||||
| ) | |||||
| // getDefaultConsumerOptions describes the options that will be used when a value isn't provided | |||||
| func getDefaultConsumerOptions(queueName string) ConsumerOptions { | |||||
| return ConsumerOptions{ | |||||
| RabbitConsumerOptions: RabbitConsumerOptions{ | |||||
| Name: "", | |||||
| AutoAck: false, | |||||
| Exclusive: false, | |||||
| NoWait: false, | |||||
| NoLocal: false, | |||||
| Args: Table{}, | |||||
| }, | |||||
| QueueOptions: QueueOptions{ | |||||
| Name: queueName, | |||||
| Durable: false, | |||||
| AutoDelete: false, | |||||
| Exclusive: false, | |||||
| NoWait: false, | |||||
| Passive: false, | |||||
| Args: Table{}, | |||||
| Declare: true, | |||||
| }, | |||||
| ExchangeOptions: ExchangeOptions{ | |||||
| Name: "", | |||||
| Kind: amqp.ExchangeDirect, | |||||
| Durable: false, | |||||
| AutoDelete: false, | |||||
| Internal: false, | |||||
| NoWait: false, | |||||
| Passive: false, | |||||
| Args: Table{}, | |||||
| Declare: false, | |||||
| }, | |||||
| Bindings: []Binding{}, | |||||
| Concurrency: 1, | |||||
| Logger: stdDebugLogger{}, | |||||
| } | |||||
| } | |||||
| func getDefaultBindingOptions() BindingOptions { | |||||
| return BindingOptions{ | |||||
| NoWait: false, | |||||
| Args: Table{}, | |||||
| Declare: true, | |||||
| } | |||||
| } | |||||
| // ConsumerOptions are used to describe how a new consumer will be created. | |||||
| // If QueueOptions is not nil, the options will be used to declare a queue | |||||
| // If ExchangeOptions is not nil, it will be used to declare an exchange | |||||
| // If there are Bindings, the queue will be bound to them | |||||
| type ConsumerOptions struct { | |||||
| RabbitConsumerOptions RabbitConsumerOptions | |||||
| QueueOptions QueueOptions | |||||
| ExchangeOptions ExchangeOptions | |||||
| Bindings []Binding | |||||
| Concurrency int | |||||
| Logger logger.Logger | |||||
| } | |||||
| // RabbitConsumerOptions are used to configure the consumer | |||||
| // on the rabbit server | |||||
| type RabbitConsumerOptions struct { | |||||
| Name string | |||||
| AutoAck bool | |||||
| Exclusive bool | |||||
| NoWait bool | |||||
| NoLocal bool | |||||
| Args Table | |||||
| } | |||||
| // QueueOptions are used to configure a queue. | |||||
| // A passive queue is assumed by RabbitMQ to already exist, and attempting to connect | |||||
| // to a non-existent queue will cause RabbitMQ to throw an exception. | |||||
| type QueueOptions struct { | |||||
| Name string | |||||
| Durable bool | |||||
| AutoDelete bool | |||||
| Exclusive bool | |||||
| NoWait bool | |||||
| Passive bool // if false, a missing queue will be created on the server | |||||
| Args Table | |||||
| Declare bool | |||||
| } | |||||
| // Binding describes the bhinding of a queue to a routing key on an exchange | |||||
| type Binding struct { | |||||
| RoutingKey string | |||||
| BindingOptions | |||||
| } | |||||
| // BindingOptions describes the options a binding can have | |||||
| type BindingOptions struct { | |||||
| NoWait bool | |||||
| Args Table | |||||
| Declare bool | |||||
| } | |||||
| // WithConsumerOptionsQueueDurable ensures the queue is a durable queue | |||||
| func WithConsumerOptionsQueueDurable(options *ConsumerOptions) { | |||||
| options.QueueOptions.Durable = true | |||||
| } | |||||
| // WithConsumerOptionsQueueAutoDelete ensures the queue is an auto-delete queue | |||||
| func WithConsumerOptionsQueueAutoDelete(options *ConsumerOptions) { | |||||
| options.QueueOptions.AutoDelete = true | |||||
| } | |||||
| // WithConsumerOptionsQueueExclusive ensures the queue is an exclusive queue | |||||
| func WithConsumerOptionsQueueExclusive(options *ConsumerOptions) { | |||||
| options.QueueOptions.Exclusive = true | |||||
| } | |||||
| // WithConsumerOptionsQueueNoWait ensures the queue is a no-wait queue | |||||
| func WithConsumerOptionsQueueNoWait(options *ConsumerOptions) { | |||||
| options.QueueOptions.NoWait = true | |||||
| } | |||||
| // WithConsumerOptionsQueuePassive ensures the queue is a passive queue | |||||
| func WithConsumerOptionsQueuePassive(options *ConsumerOptions) { | |||||
| options.QueueOptions.Passive = true | |||||
| } | |||||
| // WithConsumerOptionsQueueNoDeclare will turn off the declaration of the queue's | |||||
| // existance upon startup | |||||
| func WithConsumerOptionsQueueNoDeclare(options *ConsumerOptions) { | |||||
| options.QueueOptions.Declare = false | |||||
| } | |||||
| // WithConsumerOptionsQueueArgs adds optional args to the queue | |||||
| func WithConsumerOptionsQueueArgs(args Table) func(*ConsumerOptions) { | |||||
| return func(options *ConsumerOptions) { | |||||
| options.QueueOptions.Args = args | |||||
| } | |||||
| } | |||||
| // WithConsumerOptionsExchangeName sets the exchange name | |||||
| func WithConsumerOptionsExchangeName(name string) func(*ConsumerOptions) { | |||||
| return func(options *ConsumerOptions) { | |||||
| options.ExchangeOptions.Name = name | |||||
| } | |||||
| } | |||||
| // WithConsumerOptionsExchangeKind ensures the queue is a durable queue | |||||
| func WithConsumerOptionsExchangeKind(kind string) func(*ConsumerOptions) { | |||||
| return func(options *ConsumerOptions) { | |||||
| options.ExchangeOptions.Kind = kind | |||||
| } | |||||
| } | |||||
| // WithConsumerOptionsExchangeDurable ensures the exchange is a durable exchange | |||||
| func WithConsumerOptionsExchangeDurable(options *ConsumerOptions) { | |||||
| options.ExchangeOptions.Durable = true | |||||
| } | |||||
| // WithConsumerOptionsExchangeAutoDelete ensures the exchange is an auto-delete exchange | |||||
| func WithConsumerOptionsExchangeAutoDelete(options *ConsumerOptions) { | |||||
| options.ExchangeOptions.AutoDelete = true | |||||
| } | |||||
| // WithConsumerOptionsExchangeInternal ensures the exchange is an internal exchange | |||||
| func WithConsumerOptionsExchangeInternal(options *ConsumerOptions) { | |||||
| options.ExchangeOptions.Internal = true | |||||
| } | |||||
| // WithConsumerOptionsExchangeNoWait ensures the exchange is a no-wait exchange | |||||
| func WithConsumerOptionsExchangeNoWait(options *ConsumerOptions) { | |||||
| options.ExchangeOptions.NoWait = true | |||||
| } | |||||
| // WithConsumerOptionsExchangeDeclare stops this library from declaring the exchanges existance | |||||
| func WithConsumerOptionsExchangeDeclare(options *ConsumerOptions) { | |||||
| options.ExchangeOptions.Declare = true | |||||
| } | |||||
| // WithConsumerOptionsExchangePassive ensures the exchange is a passive exchange | |||||
| func WithConsumerOptionsExchangePassive(options *ConsumerOptions) { | |||||
| options.ExchangeOptions.Passive = true | |||||
| } | |||||
| // WithConsumerOptionsExchangeArgs adds optional args to the exchange | |||||
| func WithConsumerOptionsExchangeArgs(args Table) func(*ConsumerOptions) { | |||||
| return func(options *ConsumerOptions) { | |||||
| options.ExchangeOptions.Args = args | |||||
| } | |||||
| } | |||||
| // WithConsumerOptionsRoutingKey binds the queue to a routing key with the default binding options | |||||
| func WithConsumerOptionsRoutingKey(routingKey string) func(*ConsumerOptions) { | |||||
| return func(options *ConsumerOptions) { | |||||
| options.Bindings = append(options.Bindings, Binding{ | |||||
| RoutingKey: routingKey, | |||||
| BindingOptions: getDefaultBindingOptions(), | |||||
| }) | |||||
| } | |||||
| } | |||||
| // WithConsumerOptionsBinding adds a new binding to the queue which allows you to set the binding options | |||||
| // on a per-binding basis. Keep in mind that everything in the BindingOptions struct will default to | |||||
| // the zero value. If you want to declare your bindings for example, be sure to set Declare=true | |||||
| func WithConsumerOptionsBinding(binding Binding) func(*ConsumerOptions) { | |||||
| return func(options *ConsumerOptions) { | |||||
| options.Bindings = append(options.Bindings, binding) | |||||
| } | |||||
| } | |||||
| // WithConsumerOptionsConcurrency returns a function that sets the concurrency, which means that | |||||
| // many goroutines will be spawned to run the provided handler on messages | |||||
| func WithConsumerOptionsConcurrency(concurrency int) func(*ConsumerOptions) { | |||||
| return func(options *ConsumerOptions) { | |||||
| options.Concurrency = concurrency | |||||
| } | |||||
| } | |||||
| // WithConsumerOptionsConsumerName returns a function that sets the name on the server of this consumer | |||||
| // if unset a random name will be given | |||||
| func WithConsumerOptionsConsumerName(consumerName string) func(*ConsumerOptions) { | |||||
| return func(options *ConsumerOptions) { | |||||
| options.RabbitConsumerOptions.Name = consumerName | |||||
| } | |||||
| } | |||||
| // WithConsumerOptionsConsumerAutoAck returns a function that sets the auto acknowledge property on the server of this consumer | |||||
| // if unset the default will be used (false) | |||||
| func WithConsumerOptionsConsumerAutoAck(autoAck bool) func(*ConsumerOptions) { | |||||
| return func(options *ConsumerOptions) { | |||||
| options.RabbitConsumerOptions.AutoAck = autoAck | |||||
| } | |||||
| } | |||||
| // WithConsumerOptionsConsumerExclusive sets the consumer to exclusive, which means | |||||
| // the server will ensure that this is the sole consumer | |||||
| // from this queue. When exclusive is false, the server will fairly distribute | |||||
| // deliveries across multiple consumers. | |||||
| func WithConsumerOptionsConsumerExclusive(options *ConsumerOptions) { | |||||
| options.RabbitConsumerOptions.Exclusive = true | |||||
| } | |||||
| // WithConsumerOptionsConsumerNoWait sets the consumer to nowait, which means | |||||
| // it does not wait for the server to confirm the request and | |||||
| // immediately begin deliveries. If it is not possible to consume, a channel | |||||
| // exception will be raised and the channel will be closed. | |||||
| func WithConsumerOptionsConsumerNoWait(options *ConsumerOptions) { | |||||
| options.RabbitConsumerOptions.NoWait = true | |||||
| } | |||||
| // WithConsumerOptionsLogging uses a default logger that writes to std out | |||||
| func WithConsumerOptionsLogging(options *ConsumerOptions) { | |||||
| options.Logger = &stdDebugLogger{} | |||||
| } | |||||
| // WithConsumerOptionsLogger sets logging to a custom interface. | |||||
| // Use WithConsumerOptionsLogging to just log to stdout. | |||||
| func WithConsumerOptionsLogger(log logger.Logger) func(options *ConsumerOptions) { | |||||
| return func(options *ConsumerOptions) { | |||||
| options.Logger = log | |||||
| } | |||||
| } | |||||
| @ -0,0 +1 @@ | |||||
| multiconsumer | |||||
| @ -0,0 +1,76 @@ | |||||
| package main | |||||
| import ( | |||||
| "fmt" | |||||
| "log" | |||||
| "os" | |||||
| "os/signal" | |||||
| "syscall" | |||||
| rabbitmq "github.com/wagslane/go-rabbitmq" | |||||
| ) | |||||
| func main() { | |||||
| conn, err := rabbitmq.NewConn( | |||||
| "amqp://guest:guest@localhost", | |||||
| rabbitmq.WithConnectionOptionsLogging, | |||||
| ) | |||||
| if err != nil { | |||||
| log.Fatal(err) | |||||
| } | |||||
| defer conn.Close() | |||||
| consumer, err := rabbitmq.NewConsumer( | |||||
| conn, | |||||
| func(d rabbitmq.Delivery) rabbitmq.Action { | |||||
| log.Printf("consumed: %v", string(d.Body)) | |||||
| // rabbitmq.Ack, rabbitmq.NackDiscard, rabbitmq.NackRequeue | |||||
| return rabbitmq.Ack | |||||
| }, | |||||
| "my_queue", | |||||
| rabbitmq.WithConsumerOptionsConcurrency(2), | |||||
| rabbitmq.WithConsumerOptionsConsumerName("consumer_1"), | |||||
| rabbitmq.WithConsumerOptionsRoutingKey("my_routing_key"), | |||||
| rabbitmq.WithConsumerOptionsRoutingKey("my_routing_key_2"), | |||||
| rabbitmq.WithConsumerOptionsExchangeName("events"), | |||||
| ) | |||||
| if err != nil { | |||||
| log.Fatal(err) | |||||
| } | |||||
| defer consumer.Close() | |||||
| consumer2, err := rabbitmq.NewConsumer( | |||||
| conn, | |||||
| func(d rabbitmq.Delivery) rabbitmq.Action { | |||||
| log.Printf("consumed 2: %v", string(d.Body)) | |||||
| // rabbitmq.Ack, rabbitmq.NackDiscard, rabbitmq.NackRequeue | |||||
| return rabbitmq.Ack | |||||
| }, | |||||
| "my_queue", | |||||
| rabbitmq.WithConsumerOptionsConcurrency(2), | |||||
| rabbitmq.WithConsumerOptionsConsumerName("consumer_2"), | |||||
| rabbitmq.WithConsumerOptionsRoutingKey("my_routing_key"), | |||||
| rabbitmq.WithConsumerOptionsExchangeName("events"), | |||||
| ) | |||||
| if err != nil { | |||||
| log.Fatal(err) | |||||
| } | |||||
| defer consumer2.Close() | |||||
| // block main thread - wait for shutdown signal | |||||
| sigs := make(chan os.Signal, 1) | |||||
| done := make(chan bool, 1) | |||||
| signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) | |||||
| go func() { | |||||
| sig := <-sigs | |||||
| fmt.Println() | |||||
| fmt.Println(sig) | |||||
| done <- true | |||||
| }() | |||||
| fmt.Println("awaiting signal") | |||||
| <-done | |||||
| fmt.Println("stopping consumer") | |||||
| } | |||||
| @ -0,0 +1 @@ | |||||
| multipublisher | |||||
| @ -0,0 +1,100 @@ | |||||
| package main | |||||
| import ( | |||||
| "fmt" | |||||
| "log" | |||||
| "os" | |||||
| "os/signal" | |||||
| "syscall" | |||||
| "time" | |||||
| rabbitmq "github.com/wagslane/go-rabbitmq" | |||||
| ) | |||||
| func main() { | |||||
| conn, err := rabbitmq.NewConn( | |||||
| "amqp://guest:guest@localhost", | |||||
| rabbitmq.WithConnectionOptionsLogging, | |||||
| ) | |||||
| if err != nil { | |||||
| log.Fatal(err) | |||||
| } | |||||
| defer conn.Close() | |||||
| conn.NotifyReturn(func(r rabbitmq.Return) { | |||||
| log.Printf("message returned from server: %s", string(r.Body)) | |||||
| }) | |||||
| conn.NotifyPublish(func(c rabbitmq.Confirmation) { | |||||
| log.Printf("message confirmed from server. tag: %v, ack: %v", c.DeliveryTag, c.Ack) | |||||
| }) | |||||
| publisher, err := rabbitmq.NewPublisher( | |||||
| conn, | |||||
| rabbitmq.WithPublisherOptionsLogging, | |||||
| rabbitmq.WithPublisherOptionsExchangeName("events"), | |||||
| rabbitmq.WithPublisherOptionsExchangeDeclare, | |||||
| ) | |||||
| if err != nil { | |||||
| log.Fatal(err) | |||||
| } | |||||
| defer publisher.Close() | |||||
| publisher2, err := rabbitmq.NewPublisher( | |||||
| conn, | |||||
| rabbitmq.WithPublisherOptionsLogging, | |||||
| rabbitmq.WithPublisherOptionsExchangeName("events"), | |||||
| rabbitmq.WithPublisherOptionsExchangeDeclare, | |||||
| ) | |||||
| if err != nil { | |||||
| log.Fatal(err) | |||||
| } | |||||
| defer publisher2.Close() | |||||
| // block main thread - wait for shutdown signal | |||||
| sigs := make(chan os.Signal, 1) | |||||
| done := make(chan bool, 1) | |||||
| signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) | |||||
| go func() { | |||||
| sig := <-sigs | |||||
| fmt.Println() | |||||
| fmt.Println(sig) | |||||
| done <- true | |||||
| }() | |||||
| fmt.Println("awaiting signal") | |||||
| ticker := time.NewTicker(time.Second) | |||||
| for { | |||||
| select { | |||||
| case <-ticker.C: | |||||
| err = publisher.Publish( | |||||
| []byte("hello, world"), | |||||
| []string{"my_routing_key"}, | |||||
| rabbitmq.WithPublishOptionsContentType("application/json"), | |||||
| rabbitmq.WithPublishOptionsMandatory, | |||||
| rabbitmq.WithPublishOptionsPersistentDelivery, | |||||
| rabbitmq.WithPublishOptionsExchange("events"), | |||||
| ) | |||||
| if err != nil { | |||||
| log.Println(err) | |||||
| } | |||||
| err = publisher2.Publish( | |||||
| []byte("hello, world 2"), | |||||
| []string{"my_routing_key_2"}, | |||||
| rabbitmq.WithPublishOptionsContentType("application/json"), | |||||
| rabbitmq.WithPublishOptionsMandatory, | |||||
| rabbitmq.WithPublishOptionsPersistentDelivery, | |||||
| rabbitmq.WithPublishOptionsExchange("events"), | |||||
| ) | |||||
| if err != nil { | |||||
| log.Println(err) | |||||
| } | |||||
| case <-done: | |||||
| fmt.Println("stopping publisher") | |||||
| return | |||||
| } | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,93 @@ | |||||
| package rabbitmq | |||||
| import amqp "github.com/rabbitmq/amqp091-go" | |||||
| // PublisherOptions are used to describe a publisher's configuration. | |||||
| // Logger is a custom logging interface. | |||||
| type PublisherOptions struct { | |||||
| ExchangeOptions ExchangeOptions | |||||
| Logger Logger | |||||
| } | |||||
| // getDefaultPublisherOptions describes the options that will be used when a value isn't provided | |||||
| func getDefaultPublisherOptions() PublisherOptions { | |||||
| return PublisherOptions{ | |||||
| ExchangeOptions: ExchangeOptions{ | |||||
| Name: "", | |||||
| Kind: amqp.ExchangeDirect, | |||||
| Durable: false, | |||||
| AutoDelete: false, | |||||
| Internal: false, | |||||
| NoWait: false, | |||||
| Passive: false, | |||||
| Args: Table{}, | |||||
| Declare: false, | |||||
| }, | |||||
| Logger: stdDebugLogger{}, | |||||
| } | |||||
| } | |||||
| // WithPublisherOptionsLogging sets logging to true on the publisher options | |||||
| // and sets the | |||||
| func WithPublisherOptionsLogging(options *PublisherOptions) { | |||||
| options.Logger = &stdDebugLogger{} | |||||
| } | |||||
| // WithPublisherOptionsLogger sets logging to a custom interface. | |||||
| // Use WithPublisherOptionsLogging to just log to stdout. | |||||
| func WithPublisherOptionsLogger(log Logger) func(options *PublisherOptions) { | |||||
| return func(options *PublisherOptions) { | |||||
| options.Logger = log | |||||
| } | |||||
| } | |||||
| // WithPublisherOptionsExchangeName sets the exchange name | |||||
| func WithPublisherOptionsExchangeName(name string) func(*PublisherOptions) { | |||||
| return func(options *PublisherOptions) { | |||||
| options.ExchangeOptions.Name = name | |||||
| } | |||||
| } | |||||
| // WithPublisherOptionsExchangeKind ensures the queue is a durable queue | |||||
| func WithPublisherOptionsExchangeKind(kind string) func(*PublisherOptions) { | |||||
| return func(options *PublisherOptions) { | |||||
| options.ExchangeOptions.Kind = kind | |||||
| } | |||||
| } | |||||
| // WithPublisherOptionsExchangeDurable ensures the exchange is a durable exchange | |||||
| func WithPublisherOptionsExchangeDurable(options *PublisherOptions) { | |||||
| options.ExchangeOptions.Durable = true | |||||
| } | |||||
| // WithPublisherOptionsExchangeAutoDelete ensures the exchange is an auto-delete exchange | |||||
| func WithPublisherOptionsExchangeAutoDelete(options *PublisherOptions) { | |||||
| options.ExchangeOptions.AutoDelete = true | |||||
| } | |||||
| // WithPublisherOptionsExchangeInternal ensures the exchange is an internal exchange | |||||
| func WithPublisherOptionsExchangeInternal(options *PublisherOptions) { | |||||
| options.ExchangeOptions.Internal = true | |||||
| } | |||||
| // WithPublisherOptionsExchangeNoWait ensures the exchange is a no-wait exchange | |||||
| func WithPublisherOptionsExchangeNoWait(options *PublisherOptions) { | |||||
| options.ExchangeOptions.NoWait = true | |||||
| } | |||||
| // WithPublisherOptionsExchangeDeclare stops this library from declaring the exchanges existance | |||||
| func WithPublisherOptionsExchangeDeclare(options *PublisherOptions) { | |||||
| options.ExchangeOptions.Declare = true | |||||
| } | |||||
| // WithPublisherOptionsExchangePassive ensures the exchange is a passive exchange | |||||
| func WithPublisherOptionsExchangePassive(options *PublisherOptions) { | |||||
| options.ExchangeOptions.Passive = true | |||||
| } | |||||
| // WithPublisherOptionsExchangeArgs adds optional args to the exchange | |||||
| func WithPublisherOptionsExchangeArgs(args Table) func(*PublisherOptions) { | |||||
| return func(options *PublisherOptions) { | |||||
| options.ExchangeOptions.Args = args | |||||
| } | |||||
| } | |||||