istox 0.1.152.3 → 0.1.153

Sign up to get free protection for your applications and to get access to all the features.
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)