-
Notifications
You must be signed in to change notification settings - Fork 206
/
Copy pathmain.go
109 lines (92 loc) · 2.24 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package main
import (
"log"
"os"
"os/signal"
"syscall"
"time"
"github.com/adjust/rmq/v5"
)
const (
prefetchLimit = 1000
pollDuration = 100 * time.Millisecond
batchSize = 111
batchTimeout = time.Second
consumeDuration = time.Millisecond
shouldLog = false
)
func main() {
errChan := make(chan error, 10)
go logErrors(errChan)
connection, err := rmq.OpenConnection("consumer", "tcp", "localhost:6379", 2, errChan)
if err != nil {
panic(err)
}
for _, queueName := range []string{
"things",
"foobars",
} {
queue, err := connection.OpenQueue(queueName)
if err != nil {
panic(err)
}
if err := queue.StartConsuming(prefetchLimit, pollDuration); err != nil {
panic(err)
}
if _, err := queue.AddBatchConsumer(queueName, batchSize, batchTimeout, NewBatchConsumer(queueName)); err != nil {
panic(err)
}
}
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT)
defer signal.Stop(signals)
<-signals // wait for signal
go func() {
<-signals // hard exit on second signal (in case shutdown gets stuck)
os.Exit(1)
}()
<-connection.StopAllConsuming() // wait for all Consume() calls to finish
}
type BatchConsumer struct {
tag string
}
func NewBatchConsumer(tag string) *BatchConsumer {
return &BatchConsumer{tag: tag}
}
func (consumer *BatchConsumer) Consume(batch rmq.Deliveries) {
payloads := batch.Payloads()
debugf("start consume %q", payloads)
time.Sleep(consumeDuration)
log.Printf("%s consumed %d: %s", consumer.tag, len(batch), batch[0])
errors := batch.Ack()
if len(errors) == 0 {
debugf("acked %q", payloads)
return
}
for i, err := range errors {
debugf("failed to ack %q: %q", batch[i].Payload(), err)
}
}
func logErrors(errChan <-chan error) {
for err := range errChan {
switch err := err.(type) {
case *rmq.HeartbeatError:
if err.Count == rmq.HeartbeatErrorLimit {
log.Print("heartbeat error (limit): ", err)
} else {
log.Print("heartbeat error: ", err)
}
case *rmq.ConsumeError:
log.Print("consume error: ", err)
case *rmq.DeliveryError:
log.Print("delivery error: ", err.Delivery, err)
default:
log.Print("other error: ", err)
}
}
}
func debugf(format string, args ...interface{}) {
if shouldLog {
log.Printf(format, args...)
}
}