nulogy_message_bus_consumer 0.3.0 → 0.3.1

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: 2faa5c725b717d217b37a0c9019ecd3f3ae9d40885a2e3b1ce898e626bbb2d3c
4
- data.tar.gz: 865137198c57cfd60bdea31c482a66240a284c34d4f1149033160c28fb2a6cef
3
+ metadata.gz: b0b77dbd208bb83d34c4881d00765baac92c4fd8ba36d5f0395e5adf479fd6ca
4
+ data.tar.gz: 74360efce2d94e148f1792aa7f4b6424c656553c6ca4452cf66583a84352a315
5
5
  SHA512:
6
- metadata.gz: 82c5cf164680d27183b17b341b362c5f1ec70a26fecf79d4f8d982ea3506e107ac8e216604c5182469c627892f3c423336053a2502c8e10c574c85af5dd82402
7
- data.tar.gz: d2109e0aefef9eecebfb57425316cf36dd7cdb92a4356253efb73271f2fed5e4c1ed59e56a46b44a2dc869dd3acb5285b88ae11d6d72b15f50a7506ed85058a2
6
+ metadata.gz: 4503a0fda0106a555a2063319ff1d71127503ab0638a50b4d2fa04e55b38d109039fb7863f1162a397140c15f255f36309d15bc2f6ce3d9f8d168a2f9479f42b
7
+ data.tar.gz: af0f4d1a905cdddfb8b04f7a4b3c232e66eb32d9b90daf28ede558afd4879e529c3992147bac19f75f4b097966a020ec87ff5013e40370ddcc43325fa50d1dd3
data/Rakefile CHANGED
@@ -18,13 +18,15 @@ APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
18
18
  load "rails/tasks/engine.rake"
19
19
  load "rails/tasks/statistics.rake"
20
20
 
21
+ require "rspec/core"
22
+ require "rspec/core/rake_task"
21
23
  RSpec::Core::RakeTask.new(:spec)
22
24
  require "rubocop/rake_task"
23
25
  RuboCop::RakeTask.new
24
- task default: [:spec, :rubocop]
26
+ task default: %i[spec rubocop]
25
27
 
26
28
  require "rake/release"
27
29
 
28
30
  Rake::Release::Task.load_all do |spec|
29
- spec.version_tag = "nulogy_message_bus_producer-v#{spec.version}"
31
+ spec.version_tag = "nulogy_message_bus_consumer-v#{spec.version}"
30
32
  end
@@ -31,7 +31,7 @@ module NulogyMessageBusConsumer
31
31
  end
32
32
 
33
33
  def logger
34
- @@logger ||= NullLogger.new
34
+ @logger ||= NullLogger.new
35
35
  end
36
36
 
37
37
  def invoke_pipeline(*steps)
@@ -56,7 +56,7 @@ module NulogyMessageBusConsumer
56
56
  Steps::ConnectToMessageBus.new(config, logger),
57
57
  Steps::SeekBeginningOfTopic.new,
58
58
  Steps::StreamMessagesUntilNoneAreLeft.new(logger),
59
- Handlers::LogUnprocessedMessages.new(logger)
59
+ Handlers::LogUnprocessedMessages.new(logger),
60
60
  ])
61
61
  end
62
62
  end
@@ -7,9 +7,10 @@ module NulogyMessageBusConsumer
7
7
 
8
8
  def call(message:, **_)
9
9
  return if ProcessedMessage.exists?(id: message.id)
10
+
10
11
  @logger.warn(JSON.dump(
11
12
  event: "unprocessed_message",
12
- kafka_message: message.to_h,
13
+ kafka_message: message.to_h
13
14
  ))
14
15
  end
15
16
  end
@@ -13,13 +13,14 @@ module NulogyMessageBusConsumer
13
13
  def wait_for(attempts: 100, interval: 0.1)
14
14
  attempts.times do
15
15
  break if yield
16
+
16
17
  sleep interval
17
18
  end
18
19
  end
19
20
 
20
21
  def every_message_until_none_are_left(consumer)
21
22
  Enumerator.new do |yielder|
22
- while message = consumer.poll(250)
23
+ while (message = consumer.poll(250))
23
24
  yielder.yield(message)
24
25
  end
25
26
  end
@@ -1,9 +1,5 @@
1
1
  module NulogyMessageBusConsumer
2
2
  class Message
3
- def initialize(attrs = {})
4
- attrs.each { |key, value| instance_variable_set("@#{key}", value) }
5
- end
6
-
7
3
  attr_reader :event_data
8
4
  attr_reader :event_data_unparsed
9
5
  attr_reader :id
@@ -14,10 +10,20 @@ module NulogyMessageBusConsumer
14
10
  attr_reader :company_uuid
15
11
  attr_reader :timestamp
16
12
  attr_reader :topic
13
+ attr_reader :created_at
14
+
15
+ def initialize(attrs = {})
16
+ attrs.each { |key, value| instance_variable_set("@#{key}", value) }
17
+ end
17
18
 
18
19
  def self.from_kafka(kafka_message)
19
20
  envelope_data = JSON.parse(kafka_message.payload, symbolize_names: true)
20
- event_data = JSON.parse(envelope_data[:event_json], symbolize_names: true) rescue {}
21
+ event_data =
22
+ begin
23
+ JSON.parse(envelope_data[:event_json], symbolize_names: true)
24
+ rescue StandardError
25
+ {}
26
+ end
21
27
 
22
28
  new(
23
29
  event_data: event_data,
@@ -30,6 +36,7 @@ module NulogyMessageBusConsumer
30
36
  company_uuid: envelope_data[:company_uuid] || envelope_data[:tenant_id],
31
37
  timestamp: kafka_message.timestamp,
32
38
  topic: kafka_message.topic,
39
+ created_at: envelope_data[:created_at]
33
40
  )
34
41
  end
35
42
 
@@ -9,7 +9,7 @@ module NulogyMessageBusConsumer
9
9
  end
10
10
 
11
11
  def insert(step, after:)
12
- index = @steps.find_index { |step| step.is_a?(after) }
12
+ index = @steps.find_index { |s| s.is_a?(after) }
13
13
  @steps.insert(index + 1, step)
14
14
  end
15
15
 
@@ -25,7 +25,7 @@ module NulogyMessageBusConsumer
25
25
  @steps.reverse.reduce(last_step) do |composed_steps, previous_step|
26
26
  lambda do |**args|
27
27
  invoke_next = compose_with_merged_args(args, composed_steps)
28
- previous_step.call(**args, &invoke_next)
28
+ previous_step.call(**args, &invoke_next)
29
29
  end
30
30
  end
31
31
  end
@@ -33,7 +33,10 @@ module NulogyMessageBusConsumer
33
33
  def compose_with_merged_args(existing_args, func)
34
34
  lambda do |**yielded_args|
35
35
  args_to_be_overridden = existing_args.keys & yielded_args.keys
36
- raise "Cannot override existing argument(s): #{args_to_be_overridden.join(', ')}" if args_to_be_overridden.any?
36
+ if args_to_be_overridden.any?
37
+ raise "Cannot override existing argument(s): #{args_to_be_overridden.join(', ')}"
38
+ end
39
+
37
40
  func.call(**existing_args.merge(yielded_args))
38
41
  end
39
42
  end
@@ -1,7 +1,7 @@
1
1
  module NulogyMessageBusConsumer
2
2
  module Steps
3
3
  class CommitOnSuccess
4
- def call(kafka_consumer:, message:, **_)
4
+ def call(kafka_consumer:, **_)
5
5
  result = yield
6
6
 
7
7
  raise_if_invalid(result)
@@ -1,14 +1,15 @@
1
1
  module NulogyMessageBusConsumer
2
2
  module Steps
3
3
  class ConnectToMessageBus
4
- def initialize(config, logger)
4
+ def initialize(config, logger, kafka_consumer: nil)
5
5
  @config = config
6
6
  @logger = logger
7
+ @kafka_consumer = kafka_consumer
7
8
  end
8
9
 
9
10
  def call(**_)
10
11
  @logger.info("Connecting to the MessageBus")
11
- consumer = Rdkafka::Config.new(consumer_config).consumer
12
+ consumer = build_consumer
12
13
  @logger.info("Using consumer group id: #{@config.consumer_group_id}")
13
14
 
14
15
  consumer.subscribe(@config.topic_name)
@@ -22,6 +23,10 @@ module NulogyMessageBusConsumer
22
23
 
23
24
  private
24
25
 
26
+ def build_consumer
27
+ @kafka_consumer || Rdkafka::Config.new(consumer_config).consumer
28
+ end
29
+
25
30
  def consumer_config
26
31
  {
27
32
  "bootstrap.servers": @config.bootstrap_servers,
@@ -1,8 +1,16 @@
1
1
  module NulogyMessageBusConsumer
2
2
  module Steps
3
+ class Clock
4
+ # milliseconds since epoch
5
+ def now
6
+ Time.zone.now.to_datetime.strftime("%Q").to_i
7
+ end
8
+ end
9
+
3
10
  class LogMessages
4
- def initialize(logger)
11
+ def initialize(logger, clock: Clock.new)
5
12
  @logger = logger
13
+ @clock = clock
6
14
  end
7
15
 
8
16
  def call(message:, **_)
@@ -14,15 +22,25 @@ module NulogyMessageBusConsumer
14
22
 
15
23
  result = yield
16
24
 
25
+ millis = diff_millis(message.created_at, @clock.now)
17
26
  @logger.info(JSON.dump({
18
27
  event: "message_processed",
19
28
  kafka_message_id: message.id,
20
29
  message: "Processed #{message.id}",
21
30
  result: result,
31
+ time_to_processed: millis,
22
32
  }))
23
33
 
24
34
  result
25
35
  end
36
+
37
+ # Debezium appears to be giving us nanos since epoch
38
+ # https://github.com/debezium/debezium/blob/5a115e902cdc1dc399ec02758dd1039a33e99bc2/debezium-core/src/main/java/io/debezium/jdbc/JdbcValueConverters.java#L237
39
+ def diff_millis(oldest_nanos, newest_millis)
40
+ old_millis = oldest_nanos / 1000
41
+
42
+ newest_millis - old_millis
43
+ end
26
44
  end
27
45
  end
28
46
  end
@@ -1,3 +1,3 @@
1
1
  module NulogyMessageBusConsumer
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  namespace :message_bus_consumer do
2
2
  desc "Verifies that the messages in the message bus have been processed"
3
- task :audit => :environment do
3
+ task audit: :environment do
4
4
  config = build_audit_config
5
5
 
6
6
  NulogyMessageBusConsumer
@@ -13,4 +13,4 @@ namespace :message_bus_consumer do
13
13
  audit_config.consumer_group_id = "#{audit_config.consumer_group_id}_consumer_audit"
14
14
  NulogyMessageBusConsumer.config
15
15
  end
16
- end
16
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nulogy_message_bus_consumer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nulogy
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-05 00:00:00.000000000 Z
11
+ date: 2020-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -52,6 +52,48 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pg
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.2.3
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 1.2.3
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
55
97
  - !ruby/object:Gem::Dependency
56
98
  name: rails
57
99
  requirement: !ruby/object:Gem::Requirement
@@ -95,33 +137,33 @@ dependencies:
95
137
  - !ruby/object:Gem::Version
96
138
  version: 3.9.0
97
139
  - !ruby/object:Gem::Dependency
98
- name: rspec-rails
140
+ name: rspec-json_expectations
99
141
  requirement: !ruby/object:Gem::Requirement
100
142
  requirements:
101
143
  - - '='
102
144
  - !ruby/object:Gem::Version
103
- version: 4.0.1
145
+ version: 2.2.0
104
146
  type: :development
105
147
  prerelease: false
106
148
  version_requirements: !ruby/object:Gem::Requirement
107
149
  requirements:
108
150
  - - '='
109
151
  - !ruby/object:Gem::Version
110
- version: 4.0.1
152
+ version: 2.2.0
111
153
  - !ruby/object:Gem::Dependency
112
- name: rspec-json_expectations
154
+ name: rspec-rails
113
155
  requirement: !ruby/object:Gem::Requirement
114
156
  requirements:
115
157
  - - '='
116
158
  - !ruby/object:Gem::Version
117
- version: 2.2.0
159
+ version: 4.0.1
118
160
  type: :development
119
161
  prerelease: false
120
162
  version_requirements: !ruby/object:Gem::Requirement
121
163
  requirements:
122
164
  - - '='
123
165
  - !ruby/object:Gem::Version
124
- version: 2.2.0
166
+ version: 4.0.1
125
167
  - !ruby/object:Gem::Dependency
126
168
  name: rubocop
127
169
  requirement: !ruby/object:Gem::Requirement
@@ -137,34 +179,34 @@ dependencies:
137
179
  - !ruby/object:Gem::Version
138
180
  version: 0.81.0
139
181
  - !ruby/object:Gem::Dependency
140
- name: rubocop-rspec
182
+ name: rubocop-rails
141
183
  requirement: !ruby/object:Gem::Requirement
142
184
  requirements:
143
185
  - - '='
144
186
  - !ruby/object:Gem::Version
145
- version: 1.38.1
187
+ version: 2.5.2
146
188
  type: :development
147
189
  prerelease: false
148
190
  version_requirements: !ruby/object:Gem::Requirement
149
191
  requirements:
150
192
  - - '='
151
193
  - !ruby/object:Gem::Version
152
- version: 1.38.1
194
+ version: 2.5.2
153
195
  - !ruby/object:Gem::Dependency
154
- name: pg
196
+ name: rubocop-rspec
155
197
  requirement: !ruby/object:Gem::Requirement
156
198
  requirements:
157
199
  - - '='
158
200
  - !ruby/object:Gem::Version
159
- version: 1.2.3
201
+ version: 1.38.1
160
202
  type: :development
161
203
  prerelease: false
162
204
  version_requirements: !ruby/object:Gem::Requirement
163
205
  requirements:
164
206
  - - '='
165
207
  - !ruby/object:Gem::Version
166
- version: 1.2.3
167
- description:
208
+ version: 1.38.1
209
+ description:
168
210
  email:
169
211
  - tass@nulogy.com
170
212
  executables: []
@@ -197,7 +239,7 @@ homepage: https://github.com/nulogy/message-bus/tree/master/gems/nulogy_message_
197
239
  licenses: []
198
240
  metadata:
199
241
  allowed_push_host: https://rubygems.org/
200
- post_install_message:
242
+ post_install_message:
201
243
  rdoc_options: []
202
244
  require_paths:
203
245
  - lib
@@ -213,7 +255,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
213
255
  version: '0'
214
256
  requirements: []
215
257
  rubygems_version: 3.0.3
216
- signing_key:
258
+ signing_key:
217
259
  specification_version: 4
218
260
  summary: Code for accessing the Nulogy Message Bus
219
261
  test_files: []