istox 0.1.152.1.test15 → 0.1.152.1.test16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e6b7b281f10081914395204d820554eb676d7f7063766a0f45f3d470ad75ee3
4
- data.tar.gz: 128fe251d9c3e76627254fa2d343e3295fa073678897626bf4fafdd3b1e35978
3
+ metadata.gz: 0556d82320982ae7582d13b0a999e8985822eb66d8086e9084866ffe23ea086c
4
+ data.tar.gz: '0529d8460f758ff329dff82cb49790d3353b6d52f8f9a4a0fe848c70fd0153c7'
5
5
  SHA512:
6
- metadata.gz: 5072c8a9f84ce0e3239283a3ceebc3d3585fb0ab29b081383333760dc475716533272c33bb41b0edb4ae6eefdb07ab4b350fd50a76509f92d25d9ea04ff5c78e
7
- data.tar.gz: 37c17fbb58fb0c07a51e88afdb953d4bab5b3b60911ee5c3a4991a333b40b6fa43109c6ac646bdc76115bbb9975267e854405d1e5e0e741294545560be64a3bb
6
+ metadata.gz: 5db924c60ebc7e215e7f343f2d34cfdae12016d632857977193742236636e563615260771b5c242ea273f919b12f2b592e9406cb25510a606797c3b51a5dd4e4
7
+ data.tar.gz: 2b4f17ebfc0dfa40a6a605839ca82b3a2c62667b9efea2875fd739bc5aece73d0315dd0ff11a2e33b6d55fe3ec417daddd45f1d1310ecdd47724d49a5cf969f7
@@ -5,6 +5,29 @@ require 'istox/helpers/logger'
5
5
  module Istox
6
6
  class BunnyBoot
7
7
  class << self
8
+ ########################################################
9
+ ##
10
+ ## RABBITMQ interceptors
11
+ ##
12
+ ######################################################
13
+ def add_consumer_interceptor(interceptor)
14
+ @consumer_interceptors ||= []
15
+ @consumer_interceptors.push(interceptor)
16
+ end
17
+
18
+ def add_publisher_interceptor(interceptor)
19
+ @publisher_interceptors ||= []
20
+ @publisher_interceptors.push(interceptor)
21
+ end
22
+
23
+ def publisher_interceptors
24
+ @publisher_interceptors || []
25
+ end
26
+
27
+ def consumer_interceptors
28
+ @consumer_interceptors || []
29
+ end
30
+
8
31
  # Create physical connection to RabbitMQ
9
32
  # During failover of RabbitMQ cluster or temporary failure, there may be error and needs retry in loop
10
33
  def connection
@@ -36,16 +59,16 @@ module Istox
36
59
  def exchange(eid)
37
60
  type = data[:exchanges][eid][:type]
38
61
  name = eid
39
- settings = { durable: exchange_durable?(eid) }
62
+ settings = { durable: exchange_durable?(eid) }
40
63
  confirm = data[:exchanges][eid][:confirm] || -1
41
64
  [type, name, settings, confirm]
42
- rescue
65
+ rescue StandardError
43
66
  nil
44
67
  end
45
68
 
46
69
  def binding_exchange_id(id)
47
70
  data[:binding][id][:exchange] || :default
48
- rescue
71
+ rescue StandardError
49
72
  nil
50
73
  end
51
74
 
@@ -56,17 +79,17 @@ module Istox
56
79
  else
57
80
  data[:queues][queue][:queue_name]
58
81
  end
59
- rescue
82
+ rescue StandardError
60
83
  nil
61
84
  end
62
85
 
63
86
  def confirm_mode(eid)
64
87
  data[:exchanges][eid][:confirm] || -1
65
- rescue
88
+ rescue StandardError
66
89
  nil
67
90
  end
68
91
 
69
- def queues_keys_for_subscribe()
92
+ def queues_keys_for_subscribe
70
93
  data['queues'].keys
71
94
  end
72
95
 
@@ -89,7 +112,7 @@ module Istox
89
112
  durable = exchange_config!(exchange_name)['durable']
90
113
  durable = true if durable.nil?
91
114
  durable
92
- rescue => e
115
+ rescue StandardError => e
93
116
  raise e
94
117
  end
95
118
 
@@ -104,7 +127,7 @@ module Istox
104
127
 
105
128
  def exchange_name(consumer_key)
106
129
  queue_config_from_consumer_key!(consumer_key)['exchange']
107
- rescue
130
+ rescue StandardError
108
131
  nil
109
132
  end
110
133
 
@@ -119,43 +142,43 @@ module Istox
119
142
  name = "#{prefix}#{delimiter}#{name}" unless prefix.nil?
120
143
  name = "#{name}#{delimiter}#{suffix}" unless suffix.nil?
121
144
  name
122
- rescue
145
+ rescue StandardError
123
146
  nil
124
147
  end
125
148
 
126
149
  def queue_priority(consumer_key)
127
150
  queue_config_from_consumer_key!(consumer_key)['priority']
128
- rescue
151
+ rescue StandardError
129
152
  nil
130
153
  end
131
154
 
132
155
  def queue_worker_param(consumer_key)
133
156
  queue_config_from_consumer_key!(consumer_key)['worker_param']
134
- rescue
157
+ rescue StandardError
135
158
  nil
136
159
  end
137
160
 
138
161
  def queue_worker_param_format(consumer_key)
139
162
  queue_config_from_consumer_key!(consumer_key)['worker_param_format'] || 'open_struct'
140
- rescue
163
+ rescue StandardError
141
164
  nil
142
165
  end
143
166
 
144
167
  def queue_routing_key(consumer_key)
145
168
  queue_config_from_consumer_key!(consumer_key)['routing_key'] || (queue_name consumer_key)
146
- rescue
169
+ rescue StandardError
147
170
  nil
148
171
  end
149
172
 
150
173
  def queue_exclusive(consumer_key)
151
174
  queue_config_from_consumer_key!(consumer_key)['exclusive'] || false
152
- rescue
175
+ rescue StandardError
153
176
  nil
154
177
  end
155
178
 
156
179
  def ruby_class(consumer_key)
157
180
  queue_config_from_consumer_key!(consumer_key)['ruby_class']
158
- rescue
181
+ rescue StandardError
159
182
  nil
160
183
  end
161
184
 
@@ -175,7 +198,7 @@ module Istox
175
198
  end
176
199
 
177
200
  durable
178
- rescue
201
+ rescue StandardError
179
202
  nil
180
203
  end
181
204
 
@@ -230,7 +253,7 @@ module Istox
230
253
  persistent = e.durable?
231
254
  mandatory = false
232
255
  # Set Mandatory & Persistent flag for non-DLX and non-manual msg
233
- unless ['dlx', 'manual'].include? options[:type]
256
+ unless %w[dlx manual].include? options[:type]
234
257
  if options[:routing_key].present?
235
258
  v1 = data['publish'][eid]
236
259
  v1 = v1[options[:routing_key]] unless v1.nil?
@@ -240,10 +263,15 @@ module Istox
240
263
  end
241
264
  options.merge!(persistent: persistent)
242
265
  options.merge!(mandatory: mandatory)
243
-
244
266
  # message.merge!(locale: I18n.locale)
245
- message = JSON.dump message
246
267
 
268
+ raise 'Rabbitmq publishing message must be a hash' unless message.is_a? Hash
269
+
270
+ publisher_interceptors.each do |interceptor|
271
+ interceptor.call(message, options)
272
+ end
273
+
274
+ message = JSON.dump message
247
275
  log.debug "Publish options are: #{options}"
248
276
  log.debug "Publish message payload #{message}"
249
277
  e.publish(message, options)
@@ -277,7 +305,7 @@ module Istox
277
305
  # combination of channel_id:delivery_tag can uniquely identify a msg
278
306
  # For each retry of msg, channel_id and delivery_tag is unchanged
279
307
  # But each retry, there is new delivery_tag that should be updated
280
- id = "#{channel_id.to_s}:#{delivery_tag.to_s}"
308
+ id = "#{channel_id}:#{delivery_tag}"
281
309
 
282
310
  ::Istox::RedisBoot.sets("#{id}:payload", JSON.dump(payload), 4)
283
311
  ::Istox::RedisBoot.sets("#{id}:eid", eid.to_s, 4)
@@ -285,7 +313,7 @@ module Istox
285
313
  end
286
314
 
287
315
  def find_tracker_on_channel(channel_id, delivery_tag, key)
288
- pattern = "#{channel_id.to_s}:#{delivery_tag.to_s}:#{key}"
316
+ pattern = "#{channel_id}:#{delivery_tag}:#{key}"
289
317
  keys = find_trackers pattern
290
318
  get_tracker(keys.first)
291
319
  end
@@ -307,9 +335,7 @@ module Istox
307
335
 
308
336
  def eid(ex)
309
337
  eid = ex.name
310
- if eid.empty?
311
- eid = :default
312
- end
338
+ eid = :default if eid.empty?
313
339
 
314
340
  eid
315
341
  end
@@ -327,9 +353,9 @@ module Istox
327
353
  def data
328
354
  Hashie.logger.level = 'ERROR'
329
355
  @data = Hashie::Mash.new(
330
- YAML.safe_load(
331
- ERB.new(File.read(ENV['AMQP_CONFIG'] || 'config/amqp.yml')).result
332
- )
356
+ YAML.safe_load(
357
+ ERB.new(File.read(ENV['AMQP_CONFIG'] || 'config/amqp.yml')).result
358
+ )
333
359
  )
334
360
  end
335
361
 
@@ -356,11 +382,11 @@ module Istox
356
382
  def find_trackers(pattern)
357
383
  cursor = 0
358
384
  all_keys = []
359
- loop {
360
- cursor, keys = ::Istox::RedisBoot.scan(cursor, {:match => pattern, :count => 500}, 4)
385
+ loop do
386
+ cursor, keys = ::Istox::RedisBoot.scan(cursor, { match: pattern, count: 500 }, 4)
361
387
  all_keys += keys
362
- break if cursor == "0"
363
- }
388
+ break if cursor == '0'
389
+ end
364
390
  all_keys.uniq
365
391
  end
366
392
 
@@ -4,7 +4,6 @@ module Istox
4
4
  # Publisher is relying on BunnyBoot to publish message, please make sure BunnyBoot is initalised properly first during runtime.
5
5
  class Subscriber
6
6
  class << self
7
-
8
7
  # optionally can pass in consumer_key for single subscription / consumer_keys for multiple subcriptions
9
8
  # consumer_key must be defined in amqp.yml
10
9
  # if nothing pass in it will auto subscribe to all available consumers defined in amqp.yml queues key
@@ -81,22 +80,22 @@ module Istox
81
80
  end
82
81
 
83
82
  if manual_ack
84
- if exchange.nil?
85
- letter_exchange = active_channel.default_exchange.name
86
- else
87
- letter_exchange = exchange.name
88
- end
83
+ letter_exchange = if exchange.nil?
84
+ active_channel.default_exchange.name
85
+ else
86
+ exchange.name
87
+ end
89
88
  retry_queue = active_channel.queue("#{queue_name}.retry", arguments: {
90
- 'x-dead-letter-exchange': letter_exchange,
91
- 'x-dead-letter-routing-key': "#{queue_name}",
92
- 'x-message-ttl': (::Istox::BunnyBoot.queue_retry_gap consumer_key)
93
- })
94
- unless exchange_name.nil?
89
+ 'x-dead-letter-exchange': letter_exchange,
90
+ 'x-dead-letter-routing-key': queue_name.to_s,
91
+ 'x-message-ttl': (::Istox::BunnyBoot.queue_retry_gap consumer_key)
92
+ })
93
+ if exchange_name.nil?
94
+ exchange_retry = active_channel.default_exchange
95
+ else
95
96
  exchange_retry_name = "#{exchange_name}.retry"
96
97
  exchange_retry = active_channel.send exchange_type, exchange_retry_name, durable: exchange_durable
97
98
  retry_queue.bind exchange_retry, routing_key: "#{queue_name}.retry" if manual_ack
98
- else
99
- exchange_retry = active_channel.default_exchange
100
99
  end
101
100
  end
102
101
 
@@ -117,14 +116,14 @@ module Istox
117
116
  @workers = {} if @workers.nil?
118
117
  unless block || @workers[ruby_class]
119
118
  klass = Object.const_get(
120
- '::' + (ruby_class).camelize
119
+ '::' + ruby_class.camelize
121
120
  )
122
121
  param = ::Istox::BunnyBoot.queue_worker_param consumer_key
123
- if param.nil?
124
- @workers[ruby_class] = klass.new
125
- else
126
- @workers[ruby_class] = klass.new param
127
- end
122
+ @workers[ruby_class] = if param.nil?
123
+ klass.new
124
+ else
125
+ klass.new param
126
+ end
128
127
  end
129
128
  # Subscribe queue
130
129
  priority = ::Istox::BunnyBoot.queue_priority consumer_key
@@ -150,16 +149,23 @@ module Istox
150
149
 
151
150
  if process
152
151
  processing_payload = JSON.parse(payload)
153
- processing_payload = ::Istox::CommonHelper.to_open_struct(processing_payload) if ::Istox::BunnyBoot.queue_worker_param_format(consumer_key) == 'open_struct'
152
+ if ::Istox::BunnyBoot.queue_worker_param_format(consumer_key) == 'open_struct'
153
+ processing_payload = ::Istox::CommonHelper.to_open_struct(processing_payload)
154
+ end
154
155
  log.info "Processing in consumer: #{klass}, payload: #{processing_payload.to_h.inspect}"
155
- if @workers[ruby_class].nil?
156
- result = block.call(processing_payload, metadata, delivery_info) unless block.nil?
157
- else
158
- result = @workers[ruby_class].process(processing_payload, metadata, delivery_info)
156
+
157
+ interceptors = ::Istox::BunnyBoot.consumer_interceptors.dup
158
+
159
+ intercept(interceptors, processing_payload, metadata, delivery_info) do
160
+ if @workers[ruby_class].nil?
161
+ block&.call(processing_payload, metadata, delivery_info)
162
+ else
163
+ @workers[ruby_class].process(processing_payload, metadata, delivery_info)
164
+ end
159
165
  end
160
166
  else
161
167
  # Instead of cache msg, print log
162
- log.fatal "Drop msg at #{Time.now.to_s} for queue #{queue.name}, payload is #{JSON.dump(payload)}" if store
168
+ log.fatal "Drop msg at #{Time.now} for queue #{queue.name}, payload is #{JSON.dump(payload)}" if store
163
169
  end
164
170
  # active_channel.ack(delivery_info.delivery_tag) if manual_ack
165
171
  rescue StandardError => e
@@ -175,29 +181,44 @@ module Istox
175
181
  # here we adopt the unused priority as remaining retry_count
176
182
  if process
177
183
  processing_payload = JSON.parse(payload)
178
- processing_payload = ::Istox::CommonHelper.to_open_struct(processing_payload) if ::Istox::BunnyBoot.queue_worker_param_format(consumer_key) == 'open_struct'
184
+ if ::Istox::BunnyBoot.queue_worker_param_format(consumer_key) == 'open_struct'
185
+ processing_payload = ::Istox::CommonHelper.to_open_struct(processing_payload)
186
+ end
179
187
  ::Istox::BunnyBoot.publish(exchange_retry, processing_payload, routing_key: "#{queue_name}.retry", priority: retry_count, type: 'dlx')
180
188
  end
181
189
  end
182
- =begin
183
- # For redelivered message, call 'reject' not 'nack' in order to reschedule message to tail not head of queue
184
- if delivery_info.redelivered
185
- active_channel.reject(delivery_info.delivery_tag, true)
186
- else
187
- active_channel.nack(delivery_info.delivery_tag, false, true)
188
- end
189
- =end
190
+ # # For redelivered message, call 'reject' not 'nack' in order to reschedule message to tail not head of queue
191
+ # if delivery_info.redelivered
192
+ # active_channel.reject(delivery_info.delivery_tag, true)
193
+ # else
194
+ # active_channel.nack(delivery_info.delivery_tag, false, true)
195
+ # end
190
196
  ensure
191
197
  if manual_ack
192
- if !multiple.nil? && !result && result == multiple
193
- multiple = true
194
- else
195
- multiple = false
196
- end
198
+ multiple = if !multiple.nil? && !result && result == multiple
199
+ true
200
+ else
201
+ false
202
+ end
197
203
  active_channel.ack(delivery_info.delivery_tag, multiple)
198
204
  end
199
205
  end
200
206
  end
207
+
208
+ def intercept(interceptors, payload, metadata, delivery_info)
209
+ return yield if interceptors.none?
210
+
211
+ i = interceptors.pop
212
+ return yield unless i
213
+
214
+ i.call(payload, metadata, delivery_info) do
215
+ if interceptors.any?
216
+ intercept(interceptors, payload, metadata, delivery_info) { yield }
217
+ else
218
+ yield
219
+ end
220
+ end
221
+ end
201
222
  end
202
223
  end
203
224
  end
@@ -8,7 +8,7 @@ module Istox
8
8
  no_segment = false
9
9
 
10
10
  begin
11
- XRay.recorder.current_segment
11
+ no_segment = XRay.recorder.current_segment.blank?
12
12
  rescue XRay::ContextMissingError
13
13
  no_segment = true
14
14
  end
@@ -0,0 +1,29 @@
1
+ require 'istox/helpers/logger'
2
+ require 'aws-xray-sdk'
3
+
4
+ module Istox
5
+ module Xray
6
+ class RabbitmqConsumerInterceptor
7
+ def call(payload, _metadata, delivery_info)
8
+ payload_hash = payload.to_h
9
+
10
+ trace_id = (payload_hash[:xray_trace_id] if meta.key?(:xray_trace_id))
11
+ parent_id = (payload_hash[:xray_parent_id] if meta.key?(:xray_parent_id))
12
+
13
+ arr = [delivery_info[:exchange], delivery_info[:routing_key], payload_hash[:type]].compact
14
+
15
+ XRay.recorder.begin_segment("#{::Istox::Xray::XrayInitializer.service_name}.rabbitmq.#{arr.join('.')}",
16
+ trace_id: trace_id, parent_id: parent_id)
17
+
18
+ result = yield # this returns consumer handler message
19
+
20
+ XRay.recorder.end_segment
21
+
22
+ result
23
+ rescue StandardError => e
24
+ log.error e
25
+ raise e
26
+ end
27
+ end
28
+ end
29
+ end
@@ -4,7 +4,33 @@ require 'aws-xray-sdk'
4
4
  module Istox
5
5
  module Xray
6
6
  class RabbitmqPublisherInterceptor
7
- def call; end
7
+ def call(message, options)
8
+ no_segment = false
9
+
10
+ begin
11
+ no_segment = XRay.recorder.current_segment.blank?
12
+ rescue XRay::ContextMissingError
13
+ no_segment = true
14
+ end
15
+
16
+ ## usually we have active segment for client interceptor
17
+ ## but in some special case we might not have segment initiated
18
+ ## eg. when running from rails console,
19
+ ## in those case we will initiate the segment here manully
20
+ XRay.recorder.begin_segment('rabbitmq_publish') if no_segment
21
+
22
+ XRay.recorder.begin_subsegment("rabbitmq_publish.#{options[:routing_key]}")
23
+
24
+ message[:xray_trace_id] = XRay.recorder.current_segment.trace_id
25
+ message[:xray_parent_id] = XRay.recorder.current_segment.id
26
+
27
+ XRay.recorder.end_subsegment
28
+
29
+ XRay.recorder.end_segment if no_segment
30
+ rescue StandardError => e
31
+ log.error e
32
+ raise e
33
+ end
8
34
  end
9
35
  end
10
36
  end
@@ -33,6 +33,9 @@ module Istox
33
33
  end
34
34
 
35
35
  return unless enable_rabbitmq_trace == true
36
+
37
+ ::Istox::BunnyBoot.add_publisher_interceptor(::Istox::Xray::RabbitmqPublisherInterceptor.new)
38
+ ::Istox::BunnyBoot.add_consumer_interceptor(::Istox::Xray::RabbitmqConsumerInterceptor.new)
36
39
  end
37
40
  end
38
41
  end
data/lib/istox/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Istox
2
- VERSION = '0.1.152.1.test15'.freeze
2
+ VERSION = '0.1.152.1.test16'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: istox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.152.1.test15
4
+ version: 0.1.152.1.test16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Siong Leng
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-21 00:00:00.000000000 Z
11
+ date: 2020-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_print
@@ -468,8 +468,8 @@ files:
468
468
  - lib/istox/helpers/vault.rb
469
469
  - lib/istox/helpers/xray/grpc_client_xray_interceptor.rb
470
470
  - lib/istox/helpers/xray/grpc_server_xray_interceptor.rb
471
+ - lib/istox/helpers/xray/rabbitmq_consumer_interceptor.rb
471
472
  - lib/istox/helpers/xray/rabbitmq_publisher_interceptor.rb
472
- - lib/istox/helpers/xray/rabbitmq_subscriber_interceptor.rb
473
473
  - lib/istox/helpers/xray/xray_initializer.rb
474
474
  - lib/istox/interfaces/chainhub/transaction.rb
475
475
  - lib/istox/models/blockchain_receipt.rb
@@ -1,10 +0,0 @@
1
- require 'istox/helpers/logger'
2
- require 'aws-xray-sdk'
3
-
4
- module Istox
5
- module Xray
6
- class RabbitmqSubscriberInterceptor
7
- def call; end
8
- end
9
- end
10
- end