istox 0.1.155.1 → 0.1.156.4

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: 77900ec4b0b82e5b1b7a1128c68ca5f8274c88336102c859ec10d29a8bde749e
4
- data.tar.gz: 338432eb0c47851f7bdcaf066750b861d220e787f61769d56b8c816c4ce7004c
3
+ metadata.gz: 34b676607fe2ad0ce056c3bd9b04311e05e80e1a2d9f02aa6bbb850c220b2955
4
+ data.tar.gz: c8aa6a19a0e1723531b5004a541e4b56a7b2f285d97231f26e3a5fb2ab801d3e
5
5
  SHA512:
6
- metadata.gz: 654a77d8521ffadd0f41a6d4c2c8186628a983c85472280cef98a03eb45b4d8373058b761bab544db6f4464abe4546976f37e9f5495e4025344b4b14012da739
7
- data.tar.gz: 9c63efedc40d7d5e4bf04611234f8b97f517909fae3aad6d07af42cd4e1d22ffca8d286a3a924638009d1a01458d1a50f63774ffa4af6190eaad910630935afa
6
+ metadata.gz: 9ddb211b5311e592aa29370829407c79c940c633a99ed01fe977dbe83ff331a73978c2f0049233eed2269b6d44abdc914035ec3cfb9e4d146c6b812c07882bc9
7
+ data.tar.gz: 40ddec81359c780fc780b4c37c5e798b9c42b86cc9163fb58599c7ad2f2ee6c5b8d225f5023006beda9c9be8c97cb5545f31fc92bbb270f5cc15eb39fed3e4cc
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- istox (0.1.155)
4
+ istox (0.1.156.3)
5
5
  amazing_print
6
6
  awesome_print
7
7
  binding_of_caller
@@ -7,7 +7,8 @@ import os
7
7
 
8
8
  # HOW TO RUN: python bulk-update-version.py <version updating to, eg. 0.1.150.2>
9
9
 
10
- SERVICES = ["client-api", "admin-api", "message-api", "auth", "admin-auth"]
10
+ SERVICES = ["client-api", "admin-api", "message-api",
11
+ "auth", "admin-auth", "banking-api", "trading-api"]
11
12
 
12
13
 
13
14
  def replace(file_path, pattern, subst):
@@ -56,6 +56,10 @@ module Istox
56
56
  ch
57
57
  end
58
58
 
59
+ def channel_confirm?(ch)
60
+ ch.using_publisher_confirmations?
61
+ end
62
+
59
63
  def exchange(eid)
60
64
  type = data[:exchanges][eid][:type]
61
65
  name = eid
@@ -254,29 +258,38 @@ module Istox
254
258
 
255
259
  def publish(e, message, options = {})
256
260
  eid = eid e
261
+ # By default:
262
+ # For persistence, if exchange is durable, persistent is enabled
263
+ # For mandatory. if channel is confirmed mode, mandatory is enabled
257
264
  persistent = e.durable?
258
- mandatory = false
265
+ mandatory = channel_confirm? e.channel
266
+ options_dup = options.clone
267
+
259
268
  # Set Mandatory & Persistent flag for non-DLX and non-manual msg
260
- unless %w[dlx manual].include? options[:type]
261
- if options[:routing_key].present?
269
+ unless %w[dlx manual].include? options_dup[:type]
270
+ if options_dup[:routing_key].present?
262
271
  v1 = data['publish'][eid]
263
- v1 = v1[options[:routing_key]] unless v1.nil?
264
- persistent = v1['persistent'] unless v1.nil?
265
- mandatory = v1['mandatory'] unless v1.nil?
272
+ v1 = v1[options_dup[:routing_key]] unless v1.nil? || v1[options_dup[:routing_key]].nil?
273
+ persistent = v1['persistent'] unless v1.nil? || v1['persistent'].nil?
274
+ mandatory = v1['mandatory'] unless v1.nil? || v1['mandatory'].nil?
266
275
  end
267
276
  end
268
- options.merge!(persistent: persistent)
269
- options.merge!(mandatory: mandatory)
277
+ options_dup.merge!(persistent: persistent)
278
+ options_dup.merge!(mandatory: mandatory)
279
+
280
+ options_dup[:headers] = {} if options[:headers].nil?
281
+ options_dup[:headers][:sender] = Thread.current.object_id
282
+
270
283
  # message.merge!(locale: I18n.locale)
271
284
 
272
285
  publisher_interceptors.each do |interceptor|
273
- interceptor.call(message, options)
286
+ interceptor.call(message, options_dup)
274
287
  end
275
288
 
276
289
  message = JSON.dump message
277
- log.debug "Publish options are: #{options}"
290
+ log.debug "Publish options are: #{options_dup}"
278
291
  log.debug "Publish message payload #{message}"
279
- e.publish(message, options)
292
+ e.publish(message, options_dup)
280
293
 
281
294
  options[:message_id]
282
295
  end
@@ -1,22 +1,24 @@
1
1
  module Istox
2
2
  class Formatter
3
3
  class << self
4
- include ActionView::Helpers::NumberHelper
5
-
6
4
  # format a number, eg. 20000.134 > 20,000.14
7
- def number(input, round_mode: :half_up, precision: 2)
5
+ def number(input, round_mode: :half_up, precision: 2, abs_num: false)
8
6
  BigDecimal.mode(BigDecimal::ROUND_MODE, round_mode)
9
7
 
10
8
  input = 0 if input.blank?
11
9
 
12
10
  input = ::BigDecimal.new(input.to_s).round(precision, round_mode)
13
11
 
14
- number_with_precision(input, precision: precision, delimiter: ',')
12
+ input = input.abs if abs_num
13
+
14
+ result = format("%.#{precision}f", input)
15
+
16
+ result.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
15
17
  end
16
18
 
17
- # format a money, eg. 20000.134 > SGD 20,000.14, position can be :front or :behind
18
- def money(input, round_mode: :half_up, precision: 2, currency:, position: :front)
19
- result = number(input, round_mode: round_mode, precision: precision)
19
+ # format a money, eg. 20000.134 > SGD 20,000.14, position can be :front or :behind, abs_num: whether to absolute the number
20
+ def money(input, round_mode: :half_up, precision: 2, currency:, position: :front, abs_num: false)
21
+ result = number(input, round_mode: round_mode, precision: precision, abs_num: abs_num)
20
22
 
21
23
  return currency + ' ' + result if position == :front
22
24
 
@@ -1,6 +1,9 @@
1
1
  require 'securerandom'
2
2
  require 'istox/helpers/logger'
3
3
 
4
+ class RabbitMQPublishError < StandardError
5
+ end
6
+
4
7
  module Istox
5
8
  # Publisher is relying on BunnyBoot to publish message, please make sure BunnyBoot is initalised properly first during runtime.
6
9
  class Publisher
@@ -104,7 +107,7 @@ module Istox
104
107
  def channel
105
108
  return @channel[Thread.current.object_id] if @channel.present? && @channel[Thread.current.object_id].present?
106
109
 
107
- log.info "#{Thread.current.object_id} No channel yet, create 2 channels confirm-mode and non-confirm-mode ... ..."
110
+ log.info "Thread<#{Thread.current.object_id}> No channel yet, create 3 channels confirm-mode and non-confirm-mode ... ..."
108
111
  @channel = Hash.new if @channel.nil?
109
112
  @channel[Thread.current.object_id] = Hash.new
110
113
  @channel[Thread.current.object_id]['confirm-0'] = ::Istox::BunnyBoot.channel(connection, confirm: true)
@@ -174,38 +177,61 @@ module Istox
174
177
  # when an unroutable message is returned, the BasicReturn is fired first and then an ack is sent, firing the BasicAck second.
175
178
  # So if the current status is unroutable then we need to make sure that we don't overwrite that status with Success (ack).
176
179
  ex.on_return do |return_info, properties, content|
177
- # log.debug "Got a returned message info: #{return_info}"
178
- # log.debug "Got a returned message properties: #{properties}"
179
- # log.debug "Got a returned message content: #{content}"
180
-
181
- # ::Istox::BunnyBoot.find_trackers("message_id:#{properties[:message_id]}").each do |key|
182
- # log.debug("On_return, update key #{key} in redis on status and retry counter")
183
- # ::Istox::BunnyBoot.update_tracker_by_status(key, 2)
184
- # ::Istox::BunnyBoot.update_tracker_incr_retry(key)
185
- # end
186
-
187
- # publish(return_info[:exchange], return_info[:routing_key], content)
180
+ return_info = return_info.to_hash.deep_symbolize_keys
181
+ properties = properties.to_hash.deep_symbolize_keys
182
+ log.debug "Got a returned message info: #{return_info}"
183
+ log.debug "Got a returned message properties: #{properties}"
184
+ log.debug "Got a returned message content: #{content}"
185
+
186
+ if properties[:headers] && properties[:headers][:sender]
187
+ @error = Hash.new if @error.nil?
188
+ tid = properties[:headers][:sender]
189
+ @error[tid] = Hash.new if @error[Thread.current.object_id].nil?
190
+ @error[tid][:return_info] = return_info
191
+ @error[tid][:properties] = properties
192
+ @error[tid][:content] = content
193
+ end
188
194
  end
189
195
 
190
196
  exchanges[id] = ex
191
197
  end
192
198
 
193
- def channel_confirm?(ch)
194
- ch.using_publisher_confirmations?
195
- end
196
-
197
199
  def channel_next_tag(ch)
198
200
  ch.next_publish_seq_no
199
201
  end
200
202
 
203
+ # Handle republish: check and increase retry count
204
+ def republish(ex, options = {}, message, error)
205
+ options[:headers] = {} if options[:headers].nil?
206
+
207
+ if options[:headers][:republish].nil?
208
+ options[:headers][:republish] = true
209
+ options[:headers][:republish_count] = 1
210
+ else
211
+ options[:headers][:republish_count] += 1
212
+ if options[:headers][:republish_count] > 10
213
+ log.fatal "Already retry to publish for 10 times, and give up retry"
214
+ log.info "Publish options: #{options.inspect}"
215
+ log.info "Publish to exchange: #{ex.name}"
216
+ log.info "Publish payload: #{message.inspect}"
217
+
218
+ raise RabbitMQPublishError, "Publish fails after retries(10): #{error}"
219
+ end
220
+ end
221
+
222
+ log.info "Retry to publish for <#{options[:headers][:republish_count]}> times"
223
+ do_publish(ex, options, message)
224
+ end
225
+
201
226
  def do_publish(ex, options = {}, message)
202
227
  eid = ::Istox::BunnyBoot.eid ex
203
228
  ch = ex.channel
204
229
  channel_id = ch.id
205
- confirm = channel_confirm? ch
230
+ confirm = ::Istox::BunnyBoot.channel_confirm? ch
206
231
  mode = confirm_mode eid
207
232
 
208
233
  ::Istox::BunnyBoot.publish(ex, message, options)
234
+ =begin
209
235
  if confirm
210
236
  delivery_tag = channel_next_tag ch
211
237
  if options[:message_id].nil?
@@ -216,36 +242,52 @@ module Istox
216
242
  ::Istox::BunnyBoot.rename_tracker channel_id, options[:delivery_tag], delivery_tag
217
243
  end
218
244
  end
245
+ =end
219
246
 
220
247
  if confirm && mode == 0
221
248
  success = ex.channel.wait_for_confirms
222
249
  if success
223
- ::Istox::BunnyBoot.del_tracker_on_channel channel_id
250
+ log.debug("Message confirm success: remove message for #{channel_id}")
251
+ if @error.nil? || @error[Thread.current.object_id].nil?
252
+ # republish(ex, options, message, 'simulate errors')
253
+ true
254
+ else
255
+ error = @error[Thread.current.object_id][:return_info][:reply_text]
256
+ @error[Thread.current.object_id] = nil
257
+ republish(ex, options, message, error)
258
+ end
224
259
  else
225
260
  ex.channel.nacked_set.each do |n|
226
261
  log.debug("Publish Error: UNACK delivery tag is #{n}, republish message")
227
- options = ::Istox::BunnyBoot.find_tracker_on_channel(channel_id, n, 'options')
228
- options = JSON.parse(options, :symbolize_names => true)
229
- options[:delivery_tag] = n
230
- do_publish(ex, options, message)
262
+ # options = ::Istox::BunnyBoot.find_tracker_on_channel(channel_id, n, 'options')
263
+ # options = JSON.parse(options, :symbolize_names => true)
264
+ # options[:delivery_tag] = n
265
+ republish(ex, options, message, 'broker processing fails')
231
266
  end
232
267
  end
233
268
  end
234
269
  rescue Bunny::ConnectionClosedError => e
235
- log.debug "Publish fails due to #{e}"
236
- sleep 1
237
- do_publish(ex,options,message)
270
+ log.error "Publish fails due to #{e}"
271
+ # For network related retry, sleep 2 second before retry
272
+ # Because it may take some seconds for automatic recovery of network
273
+ sleep 2
274
+ republish(ex, options, message, e.message)
275
+ rescue RabbitMQPublishError => e
276
+ raise RabbitMQPublishError, e.message
238
277
  rescue => e
239
- log.debug "Error happens: #{e.message}"
278
+ log.error "Publish error happening: #{e.message}"
240
279
 
241
280
  # If the error indicates that the channel is already closed
242
281
  # then clear hash @channel and @exchange
282
+ # re-create channel and re-declare exchange on that channel
243
283
  if e.message.include? "cannot use a closed channel"
244
284
  @channel.delete Thread.current.object_id
245
285
  @exchanges.delete Thread.current.object_id
246
286
  ex = exchange(eid)
247
- do_publish(ex, options, message)
248
287
  end
288
+
289
+ # Republish msg
290
+ republish(ex, options, message, e.message)
249
291
  end
250
292
  end
251
293
  end
@@ -1,3 +1,3 @@
1
1
  module Istox
2
- VERSION = '0.1.155.1'.freeze
2
+ VERSION = '0.1.156.4'.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.155.1
4
+ version: 0.1.156.4
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-07-06 00:00:00.000000000 Z
11
+ date: 2020-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: amazing_print