| @ -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 | |||
| } | |||
| } | |||