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 +4 -4
- data/Rakefile +4 -2
- data/lib/nulogy_message_bus_consumer.rb +2 -2
- data/lib/nulogy_message_bus_consumer/handlers/log_unprocessed_messages.rb +2 -1
- data/lib/nulogy_message_bus_consumer/kafka_utils.rb +2 -1
- data/lib/nulogy_message_bus_consumer/message.rb +12 -5
- data/lib/nulogy_message_bus_consumer/pipeline.rb +6 -3
- data/lib/nulogy_message_bus_consumer/steps/commit_on_success.rb +1 -1
- data/lib/nulogy_message_bus_consumer/steps/connect_to_message_bus.rb +7 -2
- data/lib/nulogy_message_bus_consumer/steps/log_messages.rb +19 -1
- data/lib/nulogy_message_bus_consumer/version.rb +1 -1
- data/lib/tasks/engine/message_bus_consumer.rake +2 -2
- metadata +60 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0b77dbd208bb83d34c4881d00765baac92c4fd8ba36d5f0395e5adf479fd6ca
|
4
|
+
data.tar.gz: 74360efce2d94e148f1792aa7f4b6424c656553c6ca4452cf66583a84352a315
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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: [
|
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 = "
|
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
|
-
|
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 =
|
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 { |
|
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
|
-
|
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
|
-
|
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,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 =
|
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,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 :
|
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.
|
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
|
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-
|
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:
|
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:
|
152
|
+
version: 2.2.0
|
111
153
|
- !ruby/object:Gem::Dependency
|
112
|
-
name: rspec-
|
154
|
+
name: rspec-rails
|
113
155
|
requirement: !ruby/object:Gem::Requirement
|
114
156
|
requirements:
|
115
157
|
- - '='
|
116
158
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
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:
|
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-
|
182
|
+
name: rubocop-rails
|
141
183
|
requirement: !ruby/object:Gem::Requirement
|
142
184
|
requirements:
|
143
185
|
- - '='
|
144
186
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
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:
|
194
|
+
version: 2.5.2
|
153
195
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
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.
|
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.
|
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: []
|