1
0
mirror of https://github.com/eventials/goevents.git synced 2025-04-24 13:48:53 +08:00

Removed retries limit, now retry forever

This commit is contained in:
Germano Fronza 2017-03-09 22:51:57 -03:00
parent c919262d19
commit 52625ef13c
3 changed files with 40 additions and 66 deletions

View File

@ -24,15 +24,13 @@ type Connection struct {
// ConnectionConfig to be used when creating a new connection. // ConnectionConfig to be used when creating a new connection.
type ConnectionConfig struct { type ConnectionConfig struct {
reconnectInterval time.Duration reconnectInterval time.Duration
reconnectRetries int
} }
// NewConnection returns an AMQP Connection. // NewConnection returns an AMQP Connection.
// Uses a default ConnectionConfig with 2 second of reconnect interval and 10 retries. // Uses a default ConnectionConfig with 2 second of reconnect interval.
func NewConnection(url string) (messaging.Connection, error) { func NewConnection(url string) (messaging.Connection, error) {
return NewConnectionConfig(url, ConnectionConfig{ return NewConnectionConfig(url, ConnectionConfig{
reconnectInterval: 2 * time.Second, reconnectInterval: 2 * time.Second,
reconnectRetries: 10,
}) })
} }
@ -122,14 +120,13 @@ func (c *Connection) handleConnectionClose() {
for !c.closed { for !c.closed {
c.WaitUntilConnectionCloses() c.WaitUntilConnectionCloses()
for i := 1; i <= c.config.reconnectRetries; i++ { for i := 0; !c.closed; i++ {
err := c.reestablish() err := c.reestablish()
if err == nil { if err == nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"type": "amqp", "type": "amqp",
"attempt": i, "attempt": i,
"max_retries": c.config.reconnectRetries,
}).Info("Connection reestablished") }).Info("Connection reestablished")
for _, c := range c.reestablishs { for _, c := range c.reestablishs {
@ -138,23 +135,13 @@ func (c *Connection) handleConnectionClose() {
break break
} else { } else {
if i < c.config.reconnectRetries { log.WithFields(log.Fields{
log.WithFields(log.Fields{ "type": "amqp",
"type": "amqp", "error": err,
"error": err, "attempt": i,
"attempt": i, }).Error("Error reestablishing connection. Retrying...")
"max_retries": c.config.reconnectRetries,
}).Error("Error reestablishing connection. Retrying...")
time.Sleep(c.config.reconnectInterval) time.Sleep(c.config.reconnectInterval)
} else {
log.WithFields(log.Fields{
"type": "amqp",
"error": err,
"attempt": i,
"max_retries": c.config.reconnectRetries,
}).Panic("Error reestablishing connection. Max retries reached, giving up...")
}
} }
} }
} }

View File

@ -232,7 +232,7 @@ func (c *Consumer) Consume() {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"type": "amqp", "type": "amqp",
"queue": c.queueName, "queue": c.queueName,
}).Info("Setting up consumer channel...") }).Debug("Setting up consumer channel...")
msgs, err := c.channel.Consume( msgs, err := c.channel.Consume(
c.queueName, // queue c.queueName, // queue
@ -249,7 +249,7 @@ func (c *Consumer) Consume() {
"type": "amqp", "type": "amqp",
"queue": c.queueName, "queue": c.queueName,
"error": err, "error": err,
}).Info("Error setting up consumer...") }).Error("Error setting up consumer...")
time.Sleep(c.config.consumeRetryInterval) time.Sleep(c.config.consumeRetryInterval)
@ -269,6 +269,6 @@ func (c *Consumer) Consume() {
"type": "amqp", "type": "amqp",
"queue": c.queueName, "queue": c.queueName,
"closed": c.closed, "closed": c.closed,
}).Info("Consumption stopped") }).Info("Consumption finished")
} }
} }

View File

@ -38,15 +38,13 @@ type Producer struct {
// ProducerConfig to be used when creating a new producer. // ProducerConfig to be used when creating a new producer.
type ProducerConfig struct { type ProducerConfig struct {
publishInterval time.Duration publishInterval time.Duration
publishRetries int
} }
// NewProducer returns a new AMQP Producer. // NewProducer returns a new AMQP Producer.
// Uses a default ProducerConfig with 2 second of publish interval and 10 publish retries. // Uses a default ProducerConfig with 2 second of publish interval.
func NewProducer(c messaging.Connection, exchange string) (messaging.Producer, error) { func NewProducer(c messaging.Connection, exchange string) (messaging.Producer, error) {
return NewProducerConfig(c, exchange, ProducerConfig{ return NewProducerConfig(c, exchange, ProducerConfig{
publishInterval: 2 * time.Second, publishInterval: 2 * time.Second,
publishRetries: 10,
}) })
} }
@ -87,6 +85,10 @@ func (p *Producer) Close() {
} }
func (p *Producer) setupTopology() error { func (p *Producer) setupTopology() error {
log.WithFields(log.Fields{
"type": "amqp",
}).Debug("Setting up topology...")
p.m.Lock() p.m.Lock()
defer p.m.Unlock() defer p.m.Unlock()
@ -120,12 +122,18 @@ func (p *Producer) setupTopology() error {
return err return err
} }
log.WithFields(log.Fields{
"type": "amqp",
}).Debug("Topology ready")
return nil return nil
} }
func (p *Producer) handleReestablishedConnnection() { func (p *Producer) handleReestablishedConnnection() {
reestablishChannel := p.conn.NotifyReestablish()
for !p.closed { for !p.closed {
<-p.conn.NotifyReestablish() <-reestablishChannel
err := p.setupTopology() err := p.setupTopology()
@ -140,8 +148,7 @@ func (p *Producer) handleReestablishedConnnection() {
func (p *Producer) drainInternalQueue() { func (p *Producer) drainInternalQueue() {
for m := range p.internalQueue { for m := range p.internalQueue {
// try to publish in N attempts. for i := 0; !p.closed; i++ {
for i := 1; i <= p.config.publishRetries; i++ {
msg := amqplib.Publishing{ msg := amqplib.Publishing{
DeliveryMode: amqplib.Persistent, DeliveryMode: amqplib.Persistent,
Timestamp: time.Now(), Timestamp: time.Now(),
@ -153,54 +160,34 @@ func (p *Producer) drainInternalQueue() {
defer p.m.Unlock() defer p.m.Unlock()
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"type": "amqp", "type": "amqp",
"attempt": i, "attempt": i,
"max_retries": p.config.publishRetries,
}).Debug("Publishing message to the exchange") }).Debug("Publishing message to the exchange")
return p.channel.Publish(p.exchangeName, m.action, false, false, msg) return p.channel.Publish(p.exchangeName, m.action, false, false, msg)
}() }()
if err != nil { if err != nil {
if i < p.config.publishRetries { log.WithFields(log.Fields{
log.WithFields(log.Fields{ "type": "amqp",
"type": "amqp", "error": err,
"error": err, "attempt": i,
"attempt": i, }).Error("Error publishing message to the exchange. Retrying...")
"max_retries": p.config.publishRetries,
}).Error("Error publishing message to the exchange. Retrying...")
time.Sleep(p.config.publishInterval) time.Sleep(p.config.publishInterval)
continue continue
} else {
log.WithFields(log.Fields{
"type": "amqp",
"error": err,
"attempt": i,
"max_retries": p.config.publishRetries,
}).Error("Error publishing message to the exchange. Max retries reached, giving up...")
}
} }
select { select {
case <-p.ackChannel: case <-p.ackChannel:
goto outer // 😈 goto outer // 😈
case <-p.nackChannel: case <-p.nackChannel:
if i < p.config.publishRetries { log.WithFields(log.Fields{
log.WithFields(log.Fields{ "type": "amqp",
"type": "amqp", "attempt": i,
"attempt": i, }).Error("Error publishing message to the exchange. Retrying...")
"max_retries": p.config.publishRetries,
}).Error("Error publishing message to the exchange. Retrying...")
time.Sleep(p.config.publishInterval) time.Sleep(p.config.publishInterval)
} else {
log.WithFields(log.Fields{
"type": "amqp",
"attempt": i,
"max_retries": p.config.publishRetries,
}).Error("Error publishing message to the exchange. Max retries reached, giving up...")
}
} }
} }
outer: outer: