-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: retry logic with dlx feature on rabbitmq (#17)
- Loading branch information
Showing
12 changed files
with
285 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
version: "3.7" | ||
services: | ||
rabbitmq-test: | ||
image: rabbitmq:3.13.3-management-alpine | ||
container_name: "goqueue-rabbitmq-example-basic" | ||
hostname: rabbitmq | ||
ports: | ||
- "15671:15672" | ||
- "5672:5672" | ||
volumes: | ||
- ../../../tests/localconf/rabbitmq/rabbitmq.definition.json:/opt/definitions.json:ro | ||
- ../../../tests/localconf/rabbitmq/rabbitmq.config:/etc/rabbitmq/rabbitmq.config:ro |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
version: "3.7" | ||
services: | ||
rabbitmq-test: | ||
image: rabbitmq:3.13.3-management-alpine | ||
container_name: "goqueue-rabbitmq-example-with-retries" | ||
hostname: rabbitmq | ||
ports: | ||
- "15671:15672" | ||
- "5672:5672" | ||
volumes: | ||
- ../../../tests/localconf/rabbitmq/rabbitmq.definition.json:/opt/definitions.json:ro | ||
- ../../../tests/localconf/rabbitmq/rabbitmq.config:/etc/rabbitmq/rabbitmq.config:ro |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
|
||
amqp "github.com/rabbitmq/amqp091-go" | ||
|
||
"github.com/bxcodec/goqueue" | ||
"github.com/bxcodec/goqueue/consumer" | ||
"github.com/bxcodec/goqueue/interfaces" | ||
"github.com/bxcodec/goqueue/middleware" | ||
"github.com/bxcodec/goqueue/options" | ||
consumerOpts "github.com/bxcodec/goqueue/options/consumer" | ||
publisherOpts "github.com/bxcodec/goqueue/options/publisher" | ||
"github.com/bxcodec/goqueue/publisher" | ||
) | ||
|
||
func initExchange(ch *amqp.Channel, exchangeName string) error { | ||
return ch.ExchangeDeclare( | ||
exchangeName, | ||
"topic", | ||
true, | ||
false, | ||
false, | ||
false, | ||
nil, | ||
) | ||
} | ||
|
||
func main() { | ||
rmqDSN := "amqp://rabbitmq:rabbitmq@localhost:5672/" | ||
rmqConn, err := amqp.Dial(rmqDSN) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
rmqPub := publisher.NewPublisher( | ||
publisherOpts.PublisherPlatformRabbitMQ, | ||
publisherOpts.WithRabbitMQPublisherConfig(&publisherOpts.RabbitMQPublisherConfig{ | ||
Conn: rmqConn, | ||
PublisherChannelPoolSize: 5, | ||
}), | ||
publisherOpts.WithPublisherID("publisher_id"), | ||
publisherOpts.WithMiddlewares( | ||
middleware.HelloWorldMiddlewareExecuteBeforePublisher(), | ||
middleware.HelloWorldMiddlewareExecuteAfterPublisher(), | ||
), | ||
) | ||
|
||
requeueChannel, err := rmqConn.Channel() | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
defer requeueChannel.Close() | ||
initExchange(requeueChannel, "goqueue") | ||
|
||
consumerChannel, err := rmqConn.Channel() | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer consumerChannel.Close() | ||
rmqConsumer := consumer.NewConsumer( | ||
consumerOpts.ConsumerPlatformRabbitMQ, | ||
consumerOpts.WithRabbitMQConsumerConfig(consumerOpts.RabbitMQConfigWithDefaultTopicFanOutPattern( | ||
consumerChannel, | ||
requeueChannel, | ||
"goqueue", // exchange name | ||
[]string{"goqueue.payments.#"}, // routing keys pattern | ||
)), | ||
consumerOpts.WithConsumerID("consumer_id"), | ||
consumerOpts.WithMiddlewares( | ||
middleware.HelloWorldMiddlewareExecuteAfterInboundMessageHandler(), | ||
middleware.HelloWorldMiddlewareExecuteBeforeInboundMessageHandler(), | ||
), | ||
consumerOpts.WithMaxRetryFailedMessage(5), | ||
consumerOpts.WithBatchMessageSize(1), | ||
consumerOpts.WithQueueName("consumer_queue"), | ||
) | ||
|
||
queueSvc := goqueue.NewQueueService( | ||
options.WithConsumer(rmqConsumer), | ||
options.WithPublisher(rmqPub), | ||
options.WithMessageHandler(handler()), | ||
) | ||
go func() { | ||
for i := 0; i < 10; i++ { | ||
data := map[string]interface{}{ | ||
"message": fmt.Sprintf("Hello World %d", i), | ||
} | ||
jbyt, _ := json.Marshal(data) | ||
err := queueSvc.Publish(context.Background(), interfaces.Message{ | ||
Data: data, | ||
Action: "goqueue.payments.create", | ||
Topic: "goqueue", | ||
}) | ||
if err != nil { | ||
panic(err) | ||
} | ||
fmt.Println("Message Sent: ", string(jbyt)) | ||
} | ||
}() | ||
|
||
// change to context.Background() if you want to run it forever | ||
// ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||
// defer cancel() | ||
err = queueSvc.Start(context.Background()) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func handler() interfaces.InboundMessageHandlerFunc { | ||
return func(ctx context.Context, m interfaces.InboundMessage) (err error) { | ||
fmt.Printf("Message: %+v\n", m) | ||
// something happend, we need to requeue the message | ||
return m.RetryWithDelayFn(ctx, interfaces.ExponentialBackoffDelayFn) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,23 @@ | ||
package interfaces | ||
|
||
type DelayFn func(retries int64) (delay int64) | ||
type DelayFn func(currenRetries int64) (delay int64) | ||
|
||
var ( | ||
// ExponentialBackoffDelayFn is a delay function that implements exponential backoff. | ||
// It takes the number of retries as input and returns the delay in milliseconds. | ||
ExponentialBackoffDelayFn DelayFn = func(retries int64) (delay int64) { | ||
return 2 << retries | ||
// It takes the number of retries as input and returns the delay in seconds. | ||
ExponentialBackoffDelayFn DelayFn = func(currenRetries int64) (delay int64) { | ||
return 2 << (currenRetries - 1) | ||
} | ||
|
||
// LinearDelayFn is a delay function that implements linear delay. | ||
// It takes the number of retries as input and returns the delay in seconds. | ||
LinearDelayFn DelayFn = func(currenRetries int64) (delay int64) { | ||
return currenRetries | ||
} | ||
|
||
// NoDelayFn is a DelayFn implementation that returns 0 delay for retries. | ||
NoDelayFn DelayFn = func(retries int64) (delay int64) { | ||
NoDelayFn DelayFn = func(currenRetries int64) (delay int64) { | ||
return 0 | ||
} | ||
DefaultDelayFn DelayFn = NoDelayFn | ||
DefaultDelayFn DelayFn = LinearDelayFn | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.