|
1 | 1 | (ns ziggurat.messaging.consumer
|
2 |
| - (:require [ziggurat.mapper :as mpr] |
3 |
| - [clojure.tools.logging :as log] |
| 2 | + (:require [clojure.tools.logging :as log] |
4 | 3 | [langohr.basic :as lb]
|
5 | 4 | [langohr.channel :as lch]
|
6 | 5 | [langohr.consumers :as lcons]
|
7 |
| - [ziggurat.kafka-consumer.consumer-handler :as ch] |
8 | 6 | [taoensso.nippy :as nippy]
|
9 |
| - [ziggurat.config :refer [get-in-config]] |
| 7 | + [ziggurat.config :refer [get-in-config rabbitmq-config]] |
| 8 | + [ziggurat.kafka-consumer.consumer-handler :as ch] |
| 9 | + [ziggurat.mapper :as mpr] |
10 | 10 | [ziggurat.messaging.connection :refer [connection]]
|
11 |
| - [ziggurat.sentry :refer [sentry-reporter]] |
12 |
| - [ziggurat.messaging.util :refer :all] |
| 11 | + [ziggurat.messaging.util :as util] |
13 | 12 | [ziggurat.metrics :as metrics]
|
14 | 13 | [ziggurat.util.error :refer [report-error]]))
|
15 | 14 |
|
| 15 | +(defn- reject-message |
| 16 | + [ch delivery-tag] |
| 17 | + (lb/reject ch delivery-tag)) |
| 18 | + |
| 19 | +(defn- publish-to-dead-set |
| 20 | + [ch delivery-tag topic-entity payload] |
| 21 | + (let [{:keys [exchange-name]} (:dead-letter (rabbitmq-config)) |
| 22 | + exchange (util/prefixed-queue-name topic-entity exchange-name)] |
| 23 | + (try |
| 24 | + (lb/publish ch exchange "" payload) |
| 25 | + (catch Exception e |
| 26 | + (log/error e "Exception was encountered while publishing to RabbitMQ") |
| 27 | + (reject-message ch delivery-tag))))) |
| 28 | + |
16 | 29 | (defn convert-and-ack-message
|
17 | 30 | "De-serializes the message payload (`payload`) using `nippy/thaw` and converts it to `MessagePayload`. Acks the message
|
18 | 31 | if `ack?` is true."
|
19 |
| - [ch {:keys [delivery-tag] :as meta} ^bytes payload ack? topic-entity] |
| 32 | + [ch {:keys [delivery-tag]} ^bytes payload ack? topic-entity] |
20 | 33 | (try
|
21 | 34 | (let [message (nippy/thaw payload)]
|
22 | 35 | (when ack?
|
23 | 36 | (lb/ack ch delivery-tag))
|
24 | 37 | message)
|
25 | 38 | (catch Exception e
|
26 |
| - (lb/reject ch delivery-tag false) |
27 |
| - (report-error e "Error while decoding message") |
| 39 | + (report-error e "Error while decoding message, publishing to dead queue...") |
| 40 | + (publish-to-dead-set ch delivery-tag topic-entity payload) |
28 | 41 | (metrics/increment-count ["rabbitmq-message" "conversion"] "failure" {:topic_name (name topic-entity)})
|
29 | 42 | nil)))
|
30 | 43 |
|
|
33 | 46 | (lb/ack ch delivery-tag))
|
34 | 47 |
|
35 | 48 | (defn process-message-from-queue [ch meta payload topic-entity processing-fn]
|
36 |
| - (let [delivery-tag (:delivery-tag meta) |
37 |
| - message-payload (convert-and-ack-message ch meta payload false topic-entity)] |
| 49 | + (let [delivery-tag (:delivery-tag meta) |
| 50 | + message-payload (convert-and-ack-message ch meta payload false topic-entity)] |
38 | 51 | (when message-payload
|
39 | 52 | (log/infof "Processing message [%s] from RabbitMQ " message-payload)
|
40 | 53 | (try
|
41 | 54 | (log/debug "Calling processor-fn with the message-payload - " message-payload " with retry count - " (:retry-count message-payload))
|
42 | 55 | (processing-fn message-payload)
|
43 | 56 | (ack-message ch delivery-tag)
|
44 | 57 | (catch Exception e
|
45 |
| - (lb/reject ch delivery-tag true) |
| 58 | + (publish-to-dead-set ch delivery-tag topic-entity payload) |
46 | 59 | (report-error e "Error while processing message-payload from RabbitMQ")
|
47 | 60 | (metrics/increment-count ["rabbitmq-message" "process"] "failure" {:topic_name (name topic-entity)}))))))
|
48 | 61 |
|
|
60 | 73 | (construct-queue-name topic-entity nil))
|
61 | 74 | ([topic-entity channel]
|
62 | 75 | (if (nil? channel)
|
63 |
| - (prefixed-queue-name topic-entity (get-in-config [:rabbit-mq :dead-letter :queue-name])) |
64 |
| - (prefixed-channel-name topic-entity channel (get-in-config [:rabbit-mq :dead-letter :queue-name]))))) |
| 76 | + (util/prefixed-queue-name topic-entity (get-in-config [:rabbit-mq :dead-letter :queue-name])) |
| 77 | + (util/prefixed-channel-name topic-entity channel (get-in-config [:rabbit-mq :dead-letter :queue-name]))))) |
65 | 78 |
|
66 | 79 | (defn get-dead-set-messages
|
67 | 80 | "This method can be used to read and optionally ack messages in dead-letter queue, based on the value of `ack?`.
|
|
94 | 107 |
|
95 | 108 | (defn- start-subscriber* [ch prefetch-count queue-name wrapped-mapper-fn topic-entity]
|
96 | 109 | (lb/qos ch prefetch-count)
|
97 |
| - (let [consumer-tag (lcons/subscribe ch |
98 |
| - queue-name |
99 |
| - (message-handler wrapped-mapper-fn topic-entity) |
100 |
| - {:handle-shutdown-signal-fn (fn [consumer_tag reason] |
101 |
| - (log/infof "channel closed with consumer tag: %s, reason: %s " consumer_tag, reason)) |
102 |
| - :handle-consume-ok-fn (fn [consumer_tag] |
103 |
| - (log/infof "consumer started for %s with consumer tag %s " queue-name consumer_tag))})])) |
| 110 | + (lcons/subscribe ch |
| 111 | + queue-name |
| 112 | + (message-handler wrapped-mapper-fn topic-entity) |
| 113 | + {:handle-shutdown-signal-fn (fn [consumer_tag reason] |
| 114 | + (log/infof "channel closed with consumer tag: %s, reason: %s " consumer_tag, reason)) |
| 115 | + :handle-consume-ok-fn (fn [consumer_tag] |
| 116 | + (log/infof "consumer started for %s with consumer tag %s " queue-name consumer_tag))})) |
104 | 117 |
|
105 | 118 | (defn start-retry-subscriber* [handler-fn topic-entity]
|
106 | 119 | (when (get-in-config [:retry :enabled])
|
107 | 120 | (dotimes [_ (get-in-config [:jobs :instant :worker-count])]
|
108 | 121 | (start-subscriber* (lch/open connection)
|
109 | 122 | (get-in-config [:jobs :instant :prefetch-count])
|
110 |
| - (prefixed-queue-name topic-entity (get-in-config [:rabbit-mq :instant :queue-name])) |
| 123 | + (util/prefixed-queue-name topic-entity (get-in-config [:rabbit-mq :instant :queue-name])) |
111 | 124 | handler-fn
|
112 | 125 | topic-entity))))
|
113 | 126 |
|
|
118 | 131 | (dotimes [_ (get-in-config [:stream-router topic-entity :channels channel-key :worker-count])]
|
119 | 132 | (start-subscriber* (lch/open connection)
|
120 | 133 | 1
|
121 |
| - (prefixed-channel-name topic-entity channel-key (get-in-config [:rabbit-mq :instant :queue-name])) |
| 134 | + (util/prefixed-channel-name topic-entity channel-key (get-in-config [:rabbit-mq :instant :queue-name])) |
122 | 135 | (mpr/channel-mapper-func channel-handler-fn channel-key)
|
123 | 136 | topic-entity)))))
|
124 | 137 |
|
125 | 138 | (defn start-subscribers
|
126 | 139 | "Starts the subscriber to the instant queue of the rabbitmq"
|
127 | 140 | [stream-routes batch-routes]
|
128 | 141 | (doseq [stream-route stream-routes]
|
129 |
| - (let [topic-entity (first stream-route) |
130 |
| - handler (-> stream-route second :handler-fn) |
131 |
| - channels (-> stream-route second (dissoc :handler-fn))] |
| 142 | + (let [topic-entity (first stream-route) |
| 143 | + handler (-> stream-route second :handler-fn) |
| 144 | + channels (-> stream-route second (dissoc :handler-fn))] |
132 | 145 | (start-channels-subscriber channels topic-entity)
|
133 | 146 | (start-retry-subscriber* (mpr/mapper-func handler (keys channels)) topic-entity)))
|
134 | 147 | (doseq [batch-route batch-routes]
|
135 |
| - (let [topic-entity (first batch-route) |
136 |
| - handler (-> batch-route second :handler-fn)] |
| 148 | + (let [topic-entity (first batch-route) |
| 149 | + handler (-> batch-route second :handler-fn)] |
137 | 150 | (start-retry-subscriber* (fn [message] (ch/process handler message)) topic-entity))))
|
0 commit comments