nulogy_message_bus_consumer 0.3.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +5 -4
- data/config/credentials/message-bus-us-east-1.key +1 -0
- data/config/credentials/message-bus-us-east-1.yml.enc +1 -0
- data/lib/nulogy_message_bus_consumer.rb +18 -6
- data/lib/nulogy_message_bus_consumer/clock.rb +13 -0
- data/lib/nulogy_message_bus_consumer/config.rb +12 -4
- data/lib/nulogy_message_bus_consumer/deployment/ecs.rb +23 -0
- 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/lag_tracker.rb +53 -0
- data/lib/nulogy_message_bus_consumer/message.rb +12 -5
- data/lib/nulogy_message_bus_consumer/null_logger.rb +6 -3
- data/lib/nulogy_message_bus_consumer/pipeline.rb +6 -3
- data/lib/nulogy_message_bus_consumer/steps/commit_on_success.rb +1 -0
- data/lib/nulogy_message_bus_consumer/steps/connect_to_message_bus.rb +27 -8
- data/lib/nulogy_message_bus_consumer/steps/deduplicate_messages.rb +1 -1
- data/lib/nulogy_message_bus_consumer/steps/{monitor_replication_lag.rb → log_consumer_lag.rb} +3 -3
- data/lib/nulogy_message_bus_consumer/steps/log_messages.rb +14 -3
- data/lib/nulogy_message_bus_consumer/steps/stream_messages.rb +2 -2
- data/lib/nulogy_message_bus_consumer/steps/stream_messages_until_none_are_left.rb +2 -2
- data/lib/nulogy_message_bus_consumer/steps/supervise_consumer_lag.rb +76 -0
- data/lib/nulogy_message_bus_consumer/version.rb +1 -1
- data/lib/tasks/engine/message_bus_consumer.rake +9 -10
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/config/manifest.js +3 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
- data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +2 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/javascript/packs/application.js +15 -0
- data/spec/dummy/app/jobs/application_job.rb +7 -0
- data/spec/dummy/app/mailers/application_mailer.rb +4 -0
- data/spec/dummy/app/models/application_record.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +33 -0
- data/spec/dummy/config.ru +5 -0
- data/spec/dummy/config/application.rb +29 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/cable.yml +10 -0
- data/spec/dummy/config/credentials/message-bus-us-east-1.key +1 -0
- data/spec/dummy/config/credentials/message-bus-us-east-1.yml.enc +1 -0
- data/spec/dummy/config/database.yml +27 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +62 -0
- data/spec/dummy/config/environments/production.rb +112 -0
- data/spec/dummy/config/environments/test.rb +49 -0
- data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/spec/dummy/config/initializers/assets.rb +12 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/content_security_policy.rb +28 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/message_bus_consumer.rb +5 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +33 -0
- data/spec/dummy/config/puma.rb +36 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/spring.rb +6 -0
- data/spec/dummy/config/storage.yml +34 -0
- data/spec/dummy/db/schema.rb +21 -0
- data/spec/dummy/log/development.log +4 -0
- data/spec/dummy/log/production.log +18 -0
- data/spec/dummy/log/test.log +6083 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/dummy/public/apple-touch-icon.png +0 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/tmp/development_secret.txt +1 -0
- data/spec/integration/nulogy_message_bus_consumer/auditor_spec.rb +59 -0
- data/spec/integration/nulogy_message_bus_consumer/kafka_utils_spec.rb +41 -0
- data/spec/integration/nulogy_message_bus_consumer/steps/commit_on_success_spec.rb +131 -0
- data/spec/integration/nulogy_message_bus_consumer/steps/connect_to_message_bus_spec.rb +54 -0
- data/spec/integration/nulogy_message_bus_consumer/steps/supervise_consumer_lag_spec.rb +54 -0
- data/spec/integration/test_topic_spec.rb +39 -0
- data/spec/spec_helper.rb +49 -0
- data/spec/support/kafka.rb +74 -0
- data/spec/support/middleware_tap.rb +12 -0
- data/spec/support/test_topic.rb +48 -0
- data/spec/unit/nulogy_message_bus_consumer/config_spec.rb +20 -0
- data/spec/unit/nulogy_message_bus_consumer/lag_tracker.rb +35 -0
- data/spec/unit/nulogy_message_bus_consumer/message_spec.rb +84 -0
- data/spec/unit/nulogy_message_bus_consumer/pipeline_spec.rb +49 -0
- data/spec/unit/nulogy_message_bus_consumer/steps/commit_on_success_spec.rb +58 -0
- data/spec/unit/nulogy_message_bus_consumer/steps/deduplicate_messages_spec.rb +56 -0
- data/spec/unit/nulogy_message_bus_consumer/steps/log_messages_spec.rb +70 -0
- data/spec/unit/nulogy_message_bus_consumer/steps/monitor_replication_lag/calculator_spec.rb +63 -0
- data/spec/unit/nulogy_message_bus_consumer/steps/stream_messages_spec.rb +35 -0
- data/spec/unit/nulogy_message_bus_consumer_spec.rb +30 -0
- metadata +251 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1dc5baf6066f0cf264ecf41623c1269580c8c000bd456505b3114918048b8598
|
4
|
+
data.tar.gz: 1a2e52f75e766213995846d7214d8f4e5248f011071f7d8a3fed7fb6c0fe2f03
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02effdb3a64405b47af2b6b63d1f4be505db7dcb8e632c568645af473e307030e7e0ac6615c48dc097fefaa32987f76b539ad28cfc65f5a7de98727b09d97052
|
7
|
+
data.tar.gz: 93dde5b9d7a0c12c973f6b2516d2867cc376298417c0e3ae8529f63e52974d8e489bd833494951db8cbb418eea7df124c2df02481a85eee8b7c9a575eefc8ceb
|
data/Rakefile
CHANGED
@@ -18,13 +18,14 @@ 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
|
-
require "
|
23
|
-
|
24
|
-
task default: [:spec, :rubocop]
|
24
|
+
require "standard/rake"
|
25
|
+
task default: %i[spec standard]
|
25
26
|
|
26
27
|
require "rake/release"
|
27
28
|
|
28
29
|
Rake::Release::Task.load_all do |spec|
|
29
|
-
spec.version_tag = "
|
30
|
+
spec.version_tag = "nulogy_message_bus_consumer-v#{spec.version}"
|
30
31
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
dfa19863b2709390893da4c2fb85579a
|
@@ -0,0 +1 @@
|
|
1
|
+
/WXdqUYePaHqAq3P0iTEsrLiMfRKzp2qYYh7K+q6LUNgi4eHNv0+SoLdI1bUNb9UaGvDPGNT3fCwAdkurk5Iud16ok3b4wD6yZ7UkfqbXqZaKH/dciQ5s63p9Hiuq1rbfcqoZ3KR1SXYAwvy8vNqbdwbAzz2N66B1wE5fNibZZlrWzXJjLReiTcNyxNbCPz6vwEwFF52RntuYlIJo4Nkm8vEk3No+HWrOkM8xptr5qApbd+RowLCLZ4/kcAMDB/XPiGobf0AOFv1NUR/9ChEy20usa8Fqd6HtEn4A25HnAC0uaN0K8ZRXjxhMpnXtfMBItn7yxyJ1ubjRZK5a1xVBRU7L/CVV9ZuIsqAHL1++gH5FBrEe83ZIUhN7AzngMDlOPKGiCLiZLrm18I1AEQrD7tJLyXos15AeAzj--cER8cN0iMLwu8Le+--FL7dhMTgr6xL6SkMnYKmeg==
|
@@ -1,10 +1,14 @@
|
|
1
|
+
require "active_record/railtie"
|
2
|
+
require "active_support/core_ext/time/zones"
|
1
3
|
require "rdkafka"
|
2
4
|
|
3
5
|
require "nulogy_message_bus_consumer/engine"
|
4
|
-
|
6
|
+
require "nulogy_message_bus_consumer/clock"
|
5
7
|
require "nulogy_message_bus_consumer/config"
|
8
|
+
require "nulogy_message_bus_consumer/deployment/ecs"
|
6
9
|
require "nulogy_message_bus_consumer/handlers/log_unprocessed_messages"
|
7
10
|
require "nulogy_message_bus_consumer/kafka_utils"
|
11
|
+
require "nulogy_message_bus_consumer/lag_tracker"
|
8
12
|
require "nulogy_message_bus_consumer/message"
|
9
13
|
require "nulogy_message_bus_consumer/null_logger"
|
10
14
|
require "nulogy_message_bus_consumer/pipeline"
|
@@ -12,11 +16,12 @@ require "nulogy_message_bus_consumer/processed_message"
|
|
12
16
|
require "nulogy_message_bus_consumer/steps/commit_on_success"
|
13
17
|
require "nulogy_message_bus_consumer/steps/connect_to_message_bus"
|
14
18
|
require "nulogy_message_bus_consumer/steps/deduplicate_messages"
|
19
|
+
require "nulogy_message_bus_consumer/steps/log_consumer_lag"
|
15
20
|
require "nulogy_message_bus_consumer/steps/log_messages"
|
16
|
-
require "nulogy_message_bus_consumer/steps/monitor_replication_lag"
|
17
21
|
require "nulogy_message_bus_consumer/steps/seek_beginning_of_topic"
|
18
22
|
require "nulogy_message_bus_consumer/steps/stream_messages"
|
19
23
|
require "nulogy_message_bus_consumer/steps/stream_messages_until_none_are_left"
|
24
|
+
require "nulogy_message_bus_consumer/steps/supervise_consumer_lag"
|
20
25
|
|
21
26
|
module NulogyMessageBusConsumer
|
22
27
|
module_function
|
@@ -31,7 +36,7 @@ module NulogyMessageBusConsumer
|
|
31
36
|
end
|
32
37
|
|
33
38
|
def logger
|
34
|
-
|
39
|
+
@logger ||= NullLogger.new
|
35
40
|
end
|
36
41
|
|
37
42
|
def invoke_pipeline(*steps)
|
@@ -40,14 +45,21 @@ module NulogyMessageBusConsumer
|
|
40
45
|
|
41
46
|
def recommended_consumer_pipeline(config: self.config, logger: self.logger)
|
42
47
|
Pipeline.new([
|
43
|
-
#
|
48
|
+
# System processing/health steps.
|
49
|
+
# Note: that since they are before `StreamMessages`, they will only
|
50
|
+
# be called once, without any messages.
|
44
51
|
Steps::ConnectToMessageBus.new(config, logger),
|
45
|
-
Steps::
|
52
|
+
Steps::LogConsumerLag.new(logger),
|
53
|
+
Steps::SuperviseConsumerLag.new(
|
54
|
+
logger,
|
55
|
+
check_interval_seconds: config.lag_check_interval_seconds,
|
56
|
+
tracker: LagTracker.new(failing_checks: config.lag_checks)
|
57
|
+
),
|
46
58
|
Steps::StreamMessages.new(logger),
|
47
59
|
# Message processing steps start here.
|
48
60
|
Steps::LogMessages.new(logger),
|
49
61
|
Steps::CommitOnSuccess.new,
|
50
|
-
Steps::DeduplicateMessages.new(logger)
|
62
|
+
Steps::DeduplicateMessages.new(logger)
|
51
63
|
])
|
52
64
|
end
|
53
65
|
|
@@ -1,11 +1,19 @@
|
|
1
1
|
module NulogyMessageBusConsumer
|
2
2
|
class Config
|
3
|
-
attr_accessor :
|
4
|
-
|
5
|
-
|
3
|
+
attr_accessor :bootstrap_servers,
|
4
|
+
:client_id,
|
5
|
+
:consumer_group_id,
|
6
|
+
:lag_check_interval_seconds,
|
7
|
+
:lag_checks,
|
8
|
+
:topic_name
|
6
9
|
|
7
10
|
def initialize(options = {})
|
8
|
-
|
11
|
+
defaults = {
|
12
|
+
lag_check_interval_seconds: 20,
|
13
|
+
lag_checks: 6
|
14
|
+
}
|
15
|
+
|
16
|
+
update(defaults.merge(options))
|
9
17
|
end
|
10
18
|
|
11
19
|
def update(options = {})
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module NulogyMessageBusConsumer
|
2
|
+
module Deployment
|
3
|
+
module ECS
|
4
|
+
module_function
|
5
|
+
|
6
|
+
# Try to get the TaskID from metadata server:
|
7
|
+
# https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-metadata-endpoint-v4.html
|
8
|
+
# Otherwise, return nil
|
9
|
+
def task_id
|
10
|
+
data = `curl --silent "$ECS_CONTAINER_METADATA_URI_V4/task"`
|
11
|
+
|
12
|
+
return if data.empty?
|
13
|
+
|
14
|
+
json = JSON.parse(data)
|
15
|
+
arn = json["TaskARN"]
|
16
|
+
|
17
|
+
return unless arn
|
18
|
+
|
19
|
+
arn.split("/").last
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
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
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "set"
|
2
|
+
|
3
|
+
module NulogyMessageBusConsumer
|
4
|
+
# Keeps track of how many times a topic's partition has not changed (non-zero) lag between update calls.
|
5
|
+
class LagTracker
|
6
|
+
attr_reader :failing_checks
|
7
|
+
|
8
|
+
def initialize(failing_checks: 3)
|
9
|
+
@failing_checks = failing_checks
|
10
|
+
@tracked = Hash.new { |h, topic| h[topic] = {} }
|
11
|
+
@failed = Hash.new { |h, topic| h[topic] = Set.new }
|
12
|
+
end
|
13
|
+
|
14
|
+
def update(topic_partitions)
|
15
|
+
topic_partitions.each_pair do |topic, partitions|
|
16
|
+
partitions.each_pair do |partition, value|
|
17
|
+
update_topic_partition(topic, partition, value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def failing?
|
23
|
+
@failed.any?
|
24
|
+
end
|
25
|
+
|
26
|
+
def failed
|
27
|
+
@failed.transform_values { |v| v.to_a.sort }
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def update_topic_partition(topic, partition, value)
|
33
|
+
current_value, count = @tracked.dig(topic, partition)
|
34
|
+
|
35
|
+
new_value, new_count =
|
36
|
+
if current_value == value && !value.zero?
|
37
|
+
[current_value, count + 1]
|
38
|
+
else
|
39
|
+
[value, 0]
|
40
|
+
end
|
41
|
+
|
42
|
+
@tracked[topic][partition] = [new_value, new_count]
|
43
|
+
|
44
|
+
if new_count >= @failing_checks
|
45
|
+
@failed[topic] << partition
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def exists?(topic, partition)
|
50
|
+
@tracked.dig(topic, partition)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
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
|
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,33 +1,52 @@
|
|
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
12
|
@logger.info("Using consumer group id: #{@config.consumer_group_id}")
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
subscribe
|
15
|
+
|
16
|
+
trap("TERM") { kafka_consumer.close }
|
16
17
|
|
17
|
-
|
18
|
+
wait_for_assignment
|
18
19
|
|
19
|
-
|
20
|
-
yield(kafka_consumer: consumer)
|
20
|
+
yield(kafka_consumer: kafka_consumer)
|
21
21
|
end
|
22
22
|
|
23
23
|
private
|
24
24
|
|
25
|
+
def kafka_consumer
|
26
|
+
@kafka_consumer ||= Rdkafka::Config.new(consumer_config).consumer
|
27
|
+
end
|
28
|
+
|
25
29
|
def consumer_config
|
26
|
-
{
|
30
|
+
config = {
|
27
31
|
"bootstrap.servers": @config.bootstrap_servers,
|
28
32
|
"enable.auto.commit": false,
|
29
33
|
"group.id": @config.consumer_group_id,
|
34
|
+
"enable.auto.offset.store": false
|
30
35
|
}
|
36
|
+
|
37
|
+
config["client.id"] = @config.client_id if @config.client_id
|
38
|
+
|
39
|
+
config
|
40
|
+
end
|
41
|
+
|
42
|
+
def subscribe
|
43
|
+
kafka_consumer.subscribe(@config.topic_name)
|
44
|
+
@logger.info("Listening for kafka messages on topic #{@config.topic_name}")
|
45
|
+
end
|
46
|
+
|
47
|
+
def wait_for_assignment
|
48
|
+
KafkaUtils.wait_for_assignment(kafka_consumer)
|
49
|
+
@logger.info("Connected as client: #{kafka_consumer.member_id}")
|
31
50
|
end
|
32
51
|
end
|
33
52
|
end
|
data/lib/nulogy_message_bus_consumer/steps/{monitor_replication_lag.rb → log_consumer_lag.rb}
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
module NulogyMessageBusConsumer
|
2
2
|
module Steps
|
3
|
-
class
|
3
|
+
class LogConsumerLag
|
4
4
|
def initialize(logger)
|
5
5
|
@logger = logger
|
6
6
|
end
|
@@ -22,9 +22,9 @@ module NulogyMessageBusConsumer
|
|
22
22
|
|
23
23
|
@logger.info(JSON.dump({
|
24
24
|
event: "consumer_lag",
|
25
|
-
topics: Calculator.add_max_lag(lag_per_topic)
|
25
|
+
topics: Calculator.add_max_lag(lag_per_topic)
|
26
26
|
}))
|
27
|
-
|
27
|
+
$stdout.flush
|
28
28
|
|
29
29
|
sleep 60
|
30
30
|
end
|
@@ -1,28 +1,39 @@
|
|
1
1
|
module NulogyMessageBusConsumer
|
2
2
|
module Steps
|
3
3
|
class LogMessages
|
4
|
-
def initialize(logger)
|
4
|
+
def initialize(logger, clock: Clock.new)
|
5
5
|
@logger = logger
|
6
|
+
@clock = clock
|
6
7
|
end
|
7
8
|
|
8
9
|
def call(message:, **_)
|
9
10
|
@logger.info(JSON.dump({
|
10
11
|
event: "message_received",
|
11
12
|
kafka_message_id: message.id,
|
12
|
-
message: "Received #{message.id}"
|
13
|
+
message: "Received #{message.id}"
|
13
14
|
}))
|
14
15
|
|
15
16
|
result = yield
|
16
17
|
|
18
|
+
millis = diff_millis(message.created_at, @clock.ms)
|
17
19
|
@logger.info(JSON.dump({
|
18
20
|
event: "message_processed",
|
19
21
|
kafka_message_id: message.id,
|
20
|
-
message: "Processed #{message.id}",
|
22
|
+
message: "Processed #{message.id} (#{message.topic}##{message.partition}@#{message.offset})",
|
21
23
|
result: result,
|
24
|
+
time_to_processed: millis
|
22
25
|
}))
|
23
26
|
|
24
27
|
result
|
25
28
|
end
|
29
|
+
|
30
|
+
# Debezium appears to be giving us nanos since epoch
|
31
|
+
# https://github.com/debezium/debezium/blob/5a115e902cdc1dc399ec02758dd1039a33e99bc2/debezium-core/src/main/java/io/debezium/jdbc/JdbcValueConverters.java#L237
|
32
|
+
def diff_millis(oldest_nanos, newest_millis)
|
33
|
+
old_millis = oldest_nanos / 1000
|
34
|
+
|
35
|
+
newest_millis - old_millis
|
36
|
+
end
|
26
37
|
end
|
27
38
|
end
|
28
39
|
end
|