istox 0.1.152.3 → 0.1.153

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: 0ae1c1658b28cacf39ae2e867711f841618737369ec62116f49c3bf443635b06
4
- data.tar.gz: 7d120a6c5b570e84f281d82cde6b6e3966ed5cbe80ec7c73bcc73fa491d4cdb7
3
+ metadata.gz: c276af2b326c38c02ac4ad1de3e348f614e73aaecc3fa165a7e69692336877d0
4
+ data.tar.gz: b5a763d66966da837df5dbb2c3ca52327125d4b39c9bceb78dda349be6f6a76e
5
5
  SHA512:
6
- metadata.gz: efc6c53f12a9b790e2645f3d61ef3df973f56290e0332028dd4a9bc0577f254e13b7f69ce5b2e9277e0429204ff342d783e36705aacbb664ade098a169ed81e8
7
- data.tar.gz: ea90504c68e7bf96e5b7680f8fc417d6c1474246e5e624bf3f2a1b06ce0d999447ca12cbe80b09b0535bdd80c890875ce07b6093e908e8653ce22024be17b549
6
+ metadata.gz: f39734e70c7cb2fa068483230c74cedd2c629bb311cada44cc042fb509276cc9d6dee728234f6971cc85d351384c47d35701c84a52a80eb1f2f96bd2a9c6d466
7
+ data.tar.gz: 0de4256f59e7f8920b79a69d57e42541b911276b78c40b85b0f52e3d1feea5cdc83391d7fb42a6c7e5be3826117e0d050ab00d3ed32e6f565433a6a208ea4638
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- istox (0.1.152)
4
+ istox (0.1.153)
5
5
  awesome_print
6
6
  binding_of_caller
7
7
  bunny (>= 2.12.0)
@@ -65,8 +65,20 @@ GEM
65
65
  arel (9.0.0)
66
66
  awesome_print (1.8.0)
67
67
  aws-eventstream (1.1.0)
68
- aws-sigv4 (1.1.1)
68
+ aws-partitions (1.318.0)
69
+ aws-sdk-core (3.96.1)
70
+ aws-eventstream (~> 1, >= 1.0.2)
71
+ aws-partitions (~> 1, >= 1.239.0)
72
+ aws-sigv4 (~> 1.1)
73
+ jmespath (~> 1.0)
74
+ aws-sdk-xray (1.4.0)
75
+ aws-sdk-core (~> 3)
76
+ aws-sigv4 (~> 1.0)
77
+ aws-sigv4 (1.1.3)
69
78
  aws-eventstream (~> 1.0, >= 1.0.2)
79
+ aws-xray-sdk (0.11.4)
80
+ aws-sdk-xray (~> 1.4.0)
81
+ multi_json (~> 1)
70
82
  binding_of_caller (0.8.0)
71
83
  debug_inspector (>= 0.0.1)
72
84
  builder (3.2.4)
@@ -98,14 +110,14 @@ GEM
98
110
  ffi (1.12.2)
99
111
  globalid (0.4.2)
100
112
  activesupport (>= 4.2.0)
101
- google-protobuf (3.11.4-universal-darwin)
113
+ google-protobuf (3.12.1-universal-darwin)
102
114
  googleapis-common-protos-types (1.0.5)
103
115
  google-protobuf (~> 3.11)
104
116
  graphlient (0.3.7)
105
117
  faraday
106
118
  faraday_middleware
107
119
  graphql-client
108
- graphql (1.10.6)
120
+ graphql (1.10.10)
109
121
  graphql-client (0.16.0)
110
122
  activesupport (>= 3.0)
111
123
  graphql (~> 1.8)
@@ -128,6 +140,7 @@ GEM
128
140
  grpc (~> 1.10)
129
141
  grpc-tools (~> 1.10)
130
142
  slop (~> 4.6)
143
+ jmespath (1.4.0)
131
144
  listen (3.0.8)
132
145
  rb-fsevent (~> 0.9, >= 0.9.4)
133
146
  rb-inotify (~> 0.9, >= 0.9.7)
@@ -143,12 +156,13 @@ GEM
143
156
  mini_mime (1.0.1)
144
157
  mini_portile2 (2.4.0)
145
158
  minitest (5.14.0)
159
+ multi_json (1.14.1)
146
160
  multipart-post (2.1.1)
147
161
  nio4r (2.3.1)
148
162
  nokogiri (1.10.9)
149
163
  mini_portile2 (~> 2.4.0)
150
164
  oj (3.10.6)
151
- ougai (1.8.3)
165
+ ougai (1.8.5)
152
166
  oj (~> 3.10)
153
167
  paranoia (2.4.2)
154
168
  activerecord (>= 4.0, < 6.1)
@@ -185,7 +199,7 @@ GEM
185
199
  rake (>= 0.8.7)
186
200
  thor (>= 0.19.0, < 2.0)
187
201
  rake (10.5.0)
188
- rb-fsevent (0.10.3)
202
+ rb-fsevent (0.10.4)
189
203
  rb-inotify (0.10.1)
190
204
  ffi (~> 1.0)
191
205
  redis (4.1.3)
@@ -243,7 +257,7 @@ GEM
243
257
  tzinfo (1.2.6)
244
258
  thread_safe (~> 0.1)
245
259
  uniform_notifier (1.11.0)
246
- vault (0.13.0)
260
+ vault (0.13.2)
247
261
  aws-sigv4
248
262
  websocket-driver (0.7.0)
249
263
  websocket-extensions (>= 0.1.0)
@@ -253,6 +267,7 @@ PLATFORMS
253
267
  ruby
254
268
 
255
269
  DEPENDENCIES
270
+ aws-xray-sdk
256
271
  bullet (~> 5.7.5)
257
272
  bundler (~> 1.16)
258
273
  database_cleaner (~> 1.6.0)
@@ -44,6 +44,7 @@ Gem::Specification.new do |spec|
44
44
  spec.add_dependency 'redis-namespace', '>= 1.0.0'
45
45
  spec.add_dependency 'redis-rails', '~> 5.0.2'
46
46
  spec.add_dependency 'vault', '~> 0.1'
47
+ spec.add_development_dependency 'aws-xray-sdk'
47
48
  spec.add_development_dependency 'bullet', '~> 5.7.5'
48
49
  spec.add_development_dependency 'bundler', '~> 1.16'
49
50
  spec.add_development_dependency 'database_cleaner', '~> 1.6.0'
@@ -35,6 +35,13 @@ module Istox
35
35
  require 'istox/helpers/redis'
36
36
  require 'istox/helpers/dlm'
37
37
  require 'istox/helpers/remote_model_cache'
38
+
39
+ require 'istox/helpers/xray/grpc_client_xray_interceptor'
40
+ require 'istox/helpers/xray/grpc_server_xray_interceptor'
41
+ require 'istox/helpers/xray/rabbitmq_publisher_interceptor'
42
+ require 'istox/helpers/xray/rabbitmq_consumer_interceptor'
43
+ require 'istox/helpers/xray/xray_initializer'
44
+
38
45
  require 'istox/models/blockchain_receipt'
39
46
  require 'istox/models/concerns/blockchain_receipt_query'
40
47
  require 'istox/consumers/blockchain_status_handler'
@@ -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
 
@@ -9,6 +9,12 @@ module Istox
9
9
  @@hosts[host_type] = url
10
10
  end
11
11
 
12
+ def add_interceptors(interceptor)
13
+ @interceptors = [] unless defined?(@interceptors)
14
+
15
+ @interceptors.push(interceptor)
16
+ end
17
+
12
18
  def call(host_type, service, method, grpc_retries_count: 1, **keyword_args)
13
19
  execute(host_type, service, method, **keyword_args)
14
20
  rescue Gruf::Client::Errors::Unavailable => e
@@ -72,7 +78,7 @@ module Istox
72
78
 
73
79
  log.info 'Reinitiating to grpc host at ' + host_url
74
80
  t1 = Time.now
75
- @@services[get_key(host_type, service)] = ::Gruf::Client.new(service: service, options: { hostname: host_url }, client_options: channel_options)
81
+ @@services[get_key(host_type, service)] = ::Gruf::Client.new(service: service, options: { hostname: host_url }, client_options: client_options)
76
82
  log.info "Time taken for reinitiating grpc host: #{Time.now - t1} seconds"
77
83
  end
78
84
 
@@ -80,8 +86,11 @@ module Istox
80
86
  host_type.to_s + service.to_s
81
87
  end
82
88
 
83
- def channel_options
89
+ def client_options
90
+ @interceptors = [] unless defined?(@interceptors)
91
+
84
92
  {
93
+ interceptors: @interceptors,
85
94
  channel_args: default_channel_options
86
95
  }
87
96
  end
@@ -78,9 +78,6 @@ module Istox
78
78
  @channel[t]['confirm-1'].close
79
79
  @channel[t]['noconfirm'].close
80
80
  @channel.delete t
81
-
82
- # Remove exchange from @exchange
83
- @exchanges.delete t
84
81
  end
85
82
  end
86
83
  end.join
@@ -236,16 +233,7 @@ module Istox
236
233
  sleep 1
237
234
  do_publish(ex,options,message)
238
235
  rescue => e
239
- log.debug "Error happens: #{e.message}"
240
-
241
- # If the error indicates that the channel is already closed
242
- # then clear hash @channel and @exchange
243
- if e.message.include? "cannot use a closed channel"
244
- @channel.delete Thread.current.object_id
245
- @exchanges.delete Thread.current.object_id
246
- ex = exchange(eid)
247
- do_publish(ex, options, message)
248
- end
236
+ log.debug "Error happens: #{e}"
249
237
  end
250
238
  end
251
239
  end
@@ -15,9 +15,9 @@ module Istox
15
15
  log.debug "Writing data to cache, key: #{key}, fields: #{fields.inspect}"
16
16
  log.debug "Cache data: #{data.inspect}"
17
17
 
18
- data = data.to_json unless data.instance_of?(String)
19
-
20
18
  Thread.new do
19
+ data = data.to_json unless data.instance_of?(String)
20
+
21
21
  results = fields.map do |f|
22
22
  redis.hset(key, f.to_s, data)
23
23
  end
@@ -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
@@ -0,0 +1,40 @@
1
+ require 'istox/helpers/logger'
2
+ require 'aws-xray-sdk'
3
+
4
+ module Istox
5
+ module Xray
6
+ class GrpcClientXrayInterceptor < ::Gruf::Interceptors::ClientInterceptor
7
+ def call(request_context:)
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('grpc_request') if no_segment
21
+
22
+ XRay.recorder.begin_subsegment("grpc_request.#{request_context.method}")
23
+
24
+ request_context.metadata[:xray_trace_id] = XRay.recorder.current_segment.trace_id
25
+ request_context.metadata[:xray_parent_id] = XRay.recorder.current_segment.id
26
+
27
+ result = yield
28
+
29
+ XRay.recorder.end_subsegment
30
+
31
+ XRay.recorder.end_segment if no_segment
32
+
33
+ result
34
+ rescue StandardError => e
35
+ log.error e
36
+ raise e
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,26 @@
1
+ require 'istox/helpers/logger'
2
+ require 'aws-xray-sdk'
3
+
4
+ module Istox
5
+ module Xray
6
+ class GrpcServerXrayInterceptor < ::Gruf::Interceptors::ServerInterceptor
7
+ def call
8
+ meta = request.active_call.metadata
9
+ trace_id = (meta['xray_trace_id'] if meta.present? && meta.key?('xray_trace_id'))
10
+ parent_id = (meta['xray_parent_id'] if meta.present? && meta.key?('xray_parent_id'))
11
+
12
+ XRay.recorder.begin_segment("#{::Istox::Xray::XrayInitializer.service_name}.grpc.#{request.method_key}",
13
+ trace_id: trace_id, parent_id: parent_id)
14
+
15
+ result = yield # this returns the protobuf message
16
+
17
+ XRay.recorder.end_segment
18
+
19
+ result
20
+ rescue StandardError => e
21
+ log.error e
22
+ raise e
23
+ end
24
+ end
25
+ end
26
+ 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 payload_hash.key?(:xray_trace_id))
11
+ parent_id = (payload_hash[:xray_parent_id] if payload_hash.key?(:xray_parent_id))
12
+
13
+ arr = [delivery_info[:exchange]&.downcase, delivery_info[:routing_key]&.downcase, payload_hash[:type]&.downcase].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
@@ -0,0 +1,36 @@
1
+ require 'istox/helpers/logger'
2
+ require 'aws-xray-sdk'
3
+
4
+ module Istox
5
+ module Xray
6
+ class RabbitmqPublisherInterceptor
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
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,43 @@
1
+ require 'istox/helpers/logger'
2
+ require 'istox/helpers/xray/grpc_client_xray_interceptor'
3
+ require 'istox/helpers/xray/grpc_server_xray_interceptor'
4
+ require 'istox/helpers/xray/rabbitmq_publisher_interceptor'
5
+ require 'istox/helpers/xray/rabbitmq_consumer_interceptor'
6
+ require 'istox/helpers/logger'
7
+ require 'aws-xray-sdk'
8
+
9
+ module Istox
10
+ module Xray
11
+ class XrayInitializer
12
+ class << self
13
+ attr_reader :service_name
14
+
15
+ ## input gruf config to enable gruf/grpc tracing, eg. Gruf.configure do |config|
16
+ ## set enable_rabbitmq_trace to enable rabbitmq tracing
17
+ def init(service_name, gruf_config: nil, enable_rabbitmq_trace: nil)
18
+ Rails.application.config.xray = {
19
+ # default segment name generated by XRay middleware
20
+ daemon_address: ENV['AWS_XRAY_DAEMON_ADDRESS'],
21
+ name: service_name,
22
+ patch: %I[net_http aws_sdk],
23
+ # record db transactions as subsegments
24
+ active_record: true,
25
+ context_missing: 'LOG_ERROR'
26
+ }
27
+
28
+ @service_name = service_name
29
+
30
+ if gruf_config.present?
31
+ gruf_config.interceptors.use(::Istox::Xray::GrpcServerXrayInterceptor)
32
+ ::Istox::GrpcClient.add_interceptors(::Istox::Xray::GrpcClientXrayInterceptor.new)
33
+ end
34
+
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)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,3 +1,3 @@
1
1
  module Istox
2
- VERSION = '0.1.152.3'.freeze
2
+ VERSION = '0.1.153'.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.3
4
+ version: 0.1.153
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-06-07 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
@@ -206,6 +206,20 @@ dependencies:
206
206
  - - "~>"
207
207
  - !ruby/object:Gem::Version
208
208
  version: '0.1'
209
+ - !ruby/object:Gem::Dependency
210
+ name: aws-xray-sdk
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
209
223
  - !ruby/object:Gem::Dependency
210
224
  name: bullet
211
225
  requirement: !ruby/object:Gem::Requirement
@@ -427,7 +441,6 @@ files:
427
441
  - Rakefile
428
442
  - bin/console
429
443
  - bin/setup
430
- - bulk-update-version.py
431
444
  - istox.gemspec
432
445
  - lib/istox.rb
433
446
  - lib/istox/constants/error.rb
@@ -453,6 +466,11 @@ files:
453
466
  - lib/istox/helpers/result_handler.rb
454
467
  - lib/istox/helpers/subscriber.rb
455
468
  - lib/istox/helpers/vault.rb
469
+ - lib/istox/helpers/xray/grpc_client_xray_interceptor.rb
470
+ - lib/istox/helpers/xray/grpc_server_xray_interceptor.rb
471
+ - lib/istox/helpers/xray/rabbitmq_consumer_interceptor.rb
472
+ - lib/istox/helpers/xray/rabbitmq_publisher_interceptor.rb
473
+ - lib/istox/helpers/xray/xray_initializer.rb
456
474
  - lib/istox/interfaces/chainhub/transaction.rb
457
475
  - lib/istox/models/blockchain_receipt.rb
458
476
  - lib/istox/models/concerns/blockchain_receipt_query.rb
@@ -1,93 +0,0 @@
1
- import sys
2
- import re
3
- from tempfile import mkstemp
4
- from shutil import move, copymode
5
- from os import fdopen, remove
6
- import os
7
-
8
- # HOW TO RUN: python bulk-update-version.py <version updating to, eg. 0.1.150.2>
9
-
10
- SERVICES = ["client-api", "admin-api", "message-api", "auth", "admin-auth"]
11
-
12
-
13
- def replace(file_path, pattern, subst):
14
- # Create temp file
15
- fh, abs_path = mkstemp()
16
- with fdopen(fh, 'w') as new_file:
17
- dirname = os.path.dirname(__file__)
18
- file_path = os.path.join(dirname, file_path)
19
- if os.path.exists(file_path) == False:
20
- return
21
- with open(file_path) as old_file:
22
- for line in old_file:
23
- new_file.write(re.sub(pattern, subst, line))
24
- # Copy the file permissions from the old file to the new file
25
- copymode(file_path, abs_path)
26
- # Remove original file
27
- remove(file_path)
28
- # Move new file
29
- move(abs_path, file_path)
30
-
31
-
32
- def push_service(file_path, version, hotfix):
33
- dirname = os.path.dirname(__file__)
34
- file_path = os.path.join(dirname, file_path)
35
-
36
- if os.path.exists(file_path) == False:
37
- return
38
-
39
- if hotfix == True:
40
- branch_name = "hotfix"
41
- else:
42
- branch_name = "FIX/update-istox-gem-" + version
43
-
44
- os.chdir(file_path)
45
- os.system(
46
- "git branch -D %s &>/dev/null" % (branch_name))
47
- os.system("echo 'Deleted local branch'")
48
- os.system(
49
- "git push origin --delete %s &>/dev/null" % (branch_name))
50
- os.system("echo 'Deleted remote branch'")
51
- os.system("git fetch -a")
52
- os.system("git checkout -b %s" % (branch_name))
53
- os.system("git add Gemfile")
54
- os.system("git commit -m 'Update istox-gem version to %s'" % (version))
55
- os.system("git push --set-upstream origin %s" % (branch_name))
56
- # os.system("cd " + file_path + " && git branch -D " +
57
- # branch_name + " &>/dev/null || echo 'Deleted local branch' || git push origin --delete hotfix &>/dev/null || echo 'Deleted remote branch' || git fetch -a || git checkout -b " +
58
- # branch_name + " && git add Gemfile && git commit -m 'Update istox-gem version to "
59
- # + version + "' && git push --set-upstream origin " + branch_name)
60
-
61
-
62
- arguments = sys.argv
63
- arguments.pop(0)
64
-
65
- new_version = arguments[0]
66
-
67
- hotfix = False
68
-
69
- while True:
70
- result = raw_input("Is this a hotix? Y/N \n")
71
-
72
- if result.lower() == 'y':
73
- hotfix = True
74
- break
75
- elif result.lower() == 'n':
76
- hotfix = False
77
- break
78
- else:
79
- print("Please input only Y or N.")
80
-
81
-
82
- print("Updating services " + str(SERVICES) +
83
- " to istox-gem version " + new_version)
84
-
85
- for service in SERVICES:
86
- replace("../" + service + "/Gemfile", r"gem 'istox'.+",
87
- "gem 'istox', '" + new_version + "'")
88
-
89
- for service in SERVICES:
90
- push_service("../" + service, new_version, hotfix)
91
-
92
- print("Services " + str(SERVICES) +
93
- " has been updated to istox-gem version " + new_version)