sbmt-kafka_consumer 2.0.0
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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +34 -0
- data/Appraisals +23 -0
- data/CHANGELOG.md +292 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +296 -0
- data/Rakefile +12 -0
- data/config.ru +9 -0
- data/dip.yml +84 -0
- data/docker-compose.yml +68 -0
- data/exe/kafka_consumer +16 -0
- data/lefthook-local.dip_example.yml +4 -0
- data/lefthook.yml +6 -0
- data/lib/generators/kafka_consumer/concerns/configuration.rb +30 -0
- data/lib/generators/kafka_consumer/consumer/USAGE +24 -0
- data/lib/generators/kafka_consumer/consumer/consumer_generator.rb +41 -0
- data/lib/generators/kafka_consumer/consumer/templates/consumer.rb.erb +9 -0
- data/lib/generators/kafka_consumer/consumer/templates/consumer_group.yml.erb +13 -0
- data/lib/generators/kafka_consumer/inbox_consumer/USAGE +22 -0
- data/lib/generators/kafka_consumer/inbox_consumer/inbox_consumer_generator.rb +48 -0
- data/lib/generators/kafka_consumer/inbox_consumer/templates/consumer_group.yml.erb +22 -0
- data/lib/generators/kafka_consumer/install/USAGE +9 -0
- data/lib/generators/kafka_consumer/install/install_generator.rb +22 -0
- data/lib/generators/kafka_consumer/install/templates/Kafkafile +3 -0
- data/lib/generators/kafka_consumer/install/templates/kafka_consumer.yml +59 -0
- data/lib/sbmt/kafka_consumer/app_initializer.rb +13 -0
- data/lib/sbmt/kafka_consumer/base_consumer.rb +104 -0
- data/lib/sbmt/kafka_consumer/cli.rb +55 -0
- data/lib/sbmt/kafka_consumer/client_configurer.rb +73 -0
- data/lib/sbmt/kafka_consumer/config/auth.rb +56 -0
- data/lib/sbmt/kafka_consumer/config/consumer.rb +16 -0
- data/lib/sbmt/kafka_consumer/config/consumer_group.rb +9 -0
- data/lib/sbmt/kafka_consumer/config/deserializer.rb +15 -0
- data/lib/sbmt/kafka_consumer/config/kafka.rb +32 -0
- data/lib/sbmt/kafka_consumer/config/metrics.rb +10 -0
- data/lib/sbmt/kafka_consumer/config/probes/endpoints.rb +13 -0
- data/lib/sbmt/kafka_consumer/config/probes/liveness_probe.rb +11 -0
- data/lib/sbmt/kafka_consumer/config/probes/readiness_probe.rb +10 -0
- data/lib/sbmt/kafka_consumer/config/probes.rb +8 -0
- data/lib/sbmt/kafka_consumer/config/topic.rb +14 -0
- data/lib/sbmt/kafka_consumer/config.rb +76 -0
- data/lib/sbmt/kafka_consumer/inbox_consumer.rb +129 -0
- data/lib/sbmt/kafka_consumer/instrumentation/base_monitor.rb +25 -0
- data/lib/sbmt/kafka_consumer/instrumentation/chainable_monitor.rb +31 -0
- data/lib/sbmt/kafka_consumer/instrumentation/listener_helper.rb +47 -0
- data/lib/sbmt/kafka_consumer/instrumentation/liveness_listener.rb +71 -0
- data/lib/sbmt/kafka_consumer/instrumentation/logger_listener.rb +44 -0
- data/lib/sbmt/kafka_consumer/instrumentation/open_telemetry_loader.rb +23 -0
- data/lib/sbmt/kafka_consumer/instrumentation/open_telemetry_tracer.rb +106 -0
- data/lib/sbmt/kafka_consumer/instrumentation/readiness_listener.rb +38 -0
- data/lib/sbmt/kafka_consumer/instrumentation/sentry_tracer.rb +103 -0
- data/lib/sbmt/kafka_consumer/instrumentation/tracer.rb +18 -0
- data/lib/sbmt/kafka_consumer/instrumentation/tracing_monitor.rb +17 -0
- data/lib/sbmt/kafka_consumer/instrumentation/yabeda_metrics_listener.rb +186 -0
- data/lib/sbmt/kafka_consumer/probes/host.rb +75 -0
- data/lib/sbmt/kafka_consumer/probes/probe.rb +33 -0
- data/lib/sbmt/kafka_consumer/railtie.rb +31 -0
- data/lib/sbmt/kafka_consumer/routing/karafka_v1_consumer_mapper.rb +12 -0
- data/lib/sbmt/kafka_consumer/routing/karafka_v2_consumer_mapper.rb +9 -0
- data/lib/sbmt/kafka_consumer/serialization/base_deserializer.rb +19 -0
- data/lib/sbmt/kafka_consumer/serialization/json_deserializer.rb +18 -0
- data/lib/sbmt/kafka_consumer/serialization/null_deserializer.rb +13 -0
- data/lib/sbmt/kafka_consumer/serialization/protobuf_deserializer.rb +27 -0
- data/lib/sbmt/kafka_consumer/server.rb +35 -0
- data/lib/sbmt/kafka_consumer/simple_logging_consumer.rb +11 -0
- data/lib/sbmt/kafka_consumer/testing/shared_contexts/with_sbmt_karafka_consumer.rb +61 -0
- data/lib/sbmt/kafka_consumer/testing.rb +5 -0
- data/lib/sbmt/kafka_consumer/types.rb +15 -0
- data/lib/sbmt/kafka_consumer/version.rb +7 -0
- data/lib/sbmt/kafka_consumer/yabeda_configurer.rb +91 -0
- data/lib/sbmt/kafka_consumer.rb +59 -0
- data/rubocop/rspec.yml +29 -0
- data/sbmt-kafka_consumer.gemspec +70 -0
- metadata +571 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sbmt
|
4
|
+
module KafkaConsumer
|
5
|
+
module Serialization
|
6
|
+
class BaseDeserializer
|
7
|
+
attr_reader :skip_decoding_error
|
8
|
+
|
9
|
+
def initialize(skip_decoding_error: false)
|
10
|
+
@skip_decoding_error = skip_decoding_error
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(_message)
|
14
|
+
raise NotImplementedError, "Implement this in a subclass"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sbmt
|
4
|
+
module KafkaConsumer
|
5
|
+
module Serialization
|
6
|
+
class JsonDeserializer < BaseDeserializer
|
7
|
+
def call(message)
|
8
|
+
# nil payload can be present for example for tombstone messages
|
9
|
+
message.raw_payload.nil? ? nil : ::JSON.parse(message.raw_payload)
|
10
|
+
rescue JSON::ParserError => e
|
11
|
+
raise Sbmt::KafkaConsumer::SkipUndeserializableMessage, "cannot decode message: #{e.message}, payload: #{message.raw_payload}" if skip_decoding_error
|
12
|
+
|
13
|
+
raise
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "google/protobuf"
|
4
|
+
|
5
|
+
module Sbmt
|
6
|
+
module KafkaConsumer
|
7
|
+
module Serialization
|
8
|
+
class ProtobufDeserializer < BaseDeserializer
|
9
|
+
attr_reader :message_decoder
|
10
|
+
|
11
|
+
def initialize(message_decoder_klass:, skip_decoding_error: false)
|
12
|
+
super(skip_decoding_error: skip_decoding_error)
|
13
|
+
|
14
|
+
@message_decoder = message_decoder_klass.constantize
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(message)
|
18
|
+
message_decoder.decode(message.raw_payload)
|
19
|
+
rescue Google::Protobuf::ParseError, ArgumentError => e
|
20
|
+
raise Sbmt::KafkaConsumer::SkipUndeserializableMessage, "cannot decode message: #{e.message}, payload: #{message.raw_payload}" if skip_decoding_error
|
21
|
+
|
22
|
+
raise
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sbmt
|
4
|
+
module KafkaConsumer
|
5
|
+
class Server < Karafka::Server
|
6
|
+
class << self
|
7
|
+
# original klass tries to validate karafka-specific server cli-options which we override
|
8
|
+
# see Karafka::Server for details
|
9
|
+
def run
|
10
|
+
Karafka::Server.listeners = []
|
11
|
+
Karafka::Server.workers = []
|
12
|
+
|
13
|
+
process.on_sigint { Karafka::Server.stop }
|
14
|
+
process.on_sigquit { Karafka::Server.stop }
|
15
|
+
process.on_sigterm { Karafka::Server.stop }
|
16
|
+
process.on_sigtstp { Karafka::Server.quiet }
|
17
|
+
process.supervise
|
18
|
+
|
19
|
+
$stdout.puts "Starting server"
|
20
|
+
Karafka::Server.start
|
21
|
+
|
22
|
+
sleep(0.1) until Karafka::App.terminated?
|
23
|
+
# rubocop:disable Lint/RescueException
|
24
|
+
rescue Exception => e
|
25
|
+
$stdout.puts "Cannot start server: #{e.message}"
|
26
|
+
|
27
|
+
# rubocop:enable Lint/RescueException
|
28
|
+
Karafka::Server.stop
|
29
|
+
|
30
|
+
raise e
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_context "with sbmt karafka consumer" do
|
4
|
+
subject(:consume_with_sbmt_karafka) do
|
5
|
+
coordinator.increment
|
6
|
+
consumer.on_consume
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:coordinator) {
|
10
|
+
instance = Karafka::Processing::Coordinator.new(test_topic, 0, instance_double(Karafka::TimeTrackers::Pause))
|
11
|
+
instance.instance_variable_set(:@seek_offset, -1)
|
12
|
+
instance
|
13
|
+
}
|
14
|
+
let(:test_consumer_group) { Karafka::Routing::ConsumerGroup.new(:test_group) }
|
15
|
+
let(:test_topic) { Karafka::Routing::Topic.new(:test_topic, test_consumer_group) }
|
16
|
+
let(:kafka_client) { instance_double(Karafka::Connection::Client) }
|
17
|
+
let(:null_deserializer) { Sbmt::KafkaConsumer::Serialization::NullDeserializer.new }
|
18
|
+
|
19
|
+
let(:consumer) {
|
20
|
+
build_consumer(described_class.new)
|
21
|
+
}
|
22
|
+
|
23
|
+
before {
|
24
|
+
Sbmt::KafkaConsumer::ClientConfigurer.configure!
|
25
|
+
allow(kafka_client).to receive(:assignment_lost?).and_return(false)
|
26
|
+
allow(kafka_client).to receive(:mark_as_consumed!).and_return(true)
|
27
|
+
}
|
28
|
+
|
29
|
+
def publish_to_sbmt_karafka(raw_payload, opts = {})
|
30
|
+
message = Karafka::Messages::Message.new(raw_payload, Karafka::Messages::Metadata.new(metadata_defaults.merge(opts)))
|
31
|
+
consumer.messages = Karafka::Messages::Messages.new(
|
32
|
+
[message],
|
33
|
+
Karafka::Messages::BatchMetadata.new(
|
34
|
+
topic: test_topic.name,
|
35
|
+
partition: 0,
|
36
|
+
processed_at: Time.zone.now,
|
37
|
+
created_at: Time.zone.now
|
38
|
+
)
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Hash] message default options
|
43
|
+
def metadata_defaults
|
44
|
+
{
|
45
|
+
deserializer: null_deserializer,
|
46
|
+
headers: {},
|
47
|
+
key: nil,
|
48
|
+
offset: 0,
|
49
|
+
partition: 0,
|
50
|
+
received_at: Time.current,
|
51
|
+
topic: test_topic.name
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_consumer(instance)
|
56
|
+
instance.coordinator = coordinator
|
57
|
+
instance.client = kafka_client
|
58
|
+
instance.singleton_class.include Karafka::Processing::Strategies::Default
|
59
|
+
instance
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sbmt
|
4
|
+
module KafkaConsumer
|
5
|
+
module Types
|
6
|
+
include Dry.Types
|
7
|
+
|
8
|
+
ConfigAttrs = Dry::Types["hash"].constructor { |hsh| hsh.deep_symbolize_keys }
|
9
|
+
|
10
|
+
ConfigConsumer = Types.Constructor(Config::Consumer)
|
11
|
+
ConfigDeserializer = Types.Constructor(Config::Deserializer)
|
12
|
+
ConfigTopic = Types.Constructor(Config::Topic)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sbmt
|
4
|
+
module KafkaConsumer
|
5
|
+
class YabedaConfigurer
|
6
|
+
SIZE_BUCKETS = [1, 10, 100, 1000, 10_000, 100_000, 1_000_000].freeze
|
7
|
+
LATENCY_BUCKETS = [0.0001, 0.001, 0.01, 0.1, 1.0, 10, 100, 1000].freeze
|
8
|
+
DELAY_BUCKETS = [1, 3, 10, 30, 100, 300, 1000, 3000, 10_000, 30_000].freeze
|
9
|
+
def self.configure
|
10
|
+
Yabeda.configure do
|
11
|
+
group :kafka_api do
|
12
|
+
counter :calls,
|
13
|
+
tags: %i[client broker api],
|
14
|
+
comment: "API calls"
|
15
|
+
histogram :latency,
|
16
|
+
tags: %i[client broker api],
|
17
|
+
buckets: LATENCY_BUCKETS,
|
18
|
+
comment: "API latency"
|
19
|
+
histogram :request_size,
|
20
|
+
tags: %i[client broker api],
|
21
|
+
buckets: SIZE_BUCKETS,
|
22
|
+
comment: "API request size"
|
23
|
+
histogram :response_size,
|
24
|
+
tags: %i[client broker api],
|
25
|
+
buckets: SIZE_BUCKETS,
|
26
|
+
comment: "API response size"
|
27
|
+
counter :errors,
|
28
|
+
tags: %i[client broker api],
|
29
|
+
comment: "API errors"
|
30
|
+
end
|
31
|
+
|
32
|
+
group :kafka_consumer do
|
33
|
+
counter :consumer_group_rebalances,
|
34
|
+
tags: %i[client group_id state],
|
35
|
+
comment: "Consumer group rebalances"
|
36
|
+
|
37
|
+
counter :process_messages,
|
38
|
+
tags: %i[client group_id topic partition],
|
39
|
+
comment: "Messages consumed"
|
40
|
+
|
41
|
+
counter :process_message_errors,
|
42
|
+
tags: %i[client group_id topic partition],
|
43
|
+
comment: "Messages failed to process"
|
44
|
+
|
45
|
+
histogram :process_message_latency,
|
46
|
+
tags: %i[client group_id topic partition],
|
47
|
+
buckets: LATENCY_BUCKETS,
|
48
|
+
comment: "Consumer latency"
|
49
|
+
|
50
|
+
gauge :offset_lag,
|
51
|
+
tags: %i[client group_id topic partition],
|
52
|
+
comment: "Consumer offset lag"
|
53
|
+
|
54
|
+
gauge :time_lag,
|
55
|
+
tags: %i[client group_id topic partition],
|
56
|
+
comment: "Consumer time lag"
|
57
|
+
|
58
|
+
counter :process_batch_errors,
|
59
|
+
tags: %i[client group_id topic partition],
|
60
|
+
comment: "Messages failed to process"
|
61
|
+
|
62
|
+
histogram :process_batch_latency,
|
63
|
+
tags: %i[client group_id topic partition],
|
64
|
+
buckets: LATENCY_BUCKETS,
|
65
|
+
comment: "Consumer batch latency"
|
66
|
+
|
67
|
+
histogram :batch_size,
|
68
|
+
tags: %i[client group_id topic partition],
|
69
|
+
buckets: SIZE_BUCKETS,
|
70
|
+
comment: "Consumer batch size"
|
71
|
+
|
72
|
+
counter :leave_group_errors,
|
73
|
+
tags: %i[client group_id],
|
74
|
+
comment: "Consumer group leave errors"
|
75
|
+
|
76
|
+
gauge :pause_duration,
|
77
|
+
tags: %i[client group_id topic partition],
|
78
|
+
comment: "Consumer pause duration"
|
79
|
+
|
80
|
+
counter :inbox_consumes,
|
81
|
+
tags: %i[
|
82
|
+
client group_id topic partition
|
83
|
+
inbox_name event_name status
|
84
|
+
],
|
85
|
+
comment: "Inbox item consumes"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zeitwerk"
|
4
|
+
require "karafka"
|
5
|
+
require "active_record"
|
6
|
+
require "yabeda"
|
7
|
+
require "anyway_config"
|
8
|
+
require "thor"
|
9
|
+
require "dry/types"
|
10
|
+
require "dry-struct"
|
11
|
+
|
12
|
+
begin
|
13
|
+
require "sbmt/outbox"
|
14
|
+
rescue LoadError
|
15
|
+
# sbmt-outbox is an optional dependency
|
16
|
+
end
|
17
|
+
|
18
|
+
require "anyway/rails" if defined?(Rails)
|
19
|
+
require_relative "kafka_consumer/railtie" if defined?(Rails::Railtie)
|
20
|
+
|
21
|
+
module Sbmt
|
22
|
+
module KafkaConsumer
|
23
|
+
class << self
|
24
|
+
delegate :monitor, to: Karafka
|
25
|
+
|
26
|
+
def logger
|
27
|
+
@logger ||= Rails.logger
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Error < StandardError; end
|
32
|
+
|
33
|
+
class SkipUndeserializableMessage < Error; end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
loader = Zeitwerk::Loader.new
|
38
|
+
# we need to set parent dir as gem autoloading root
|
39
|
+
# see https://github.com/fxn/zeitwerk/issues/138#issuecomment-709640940 for details
|
40
|
+
loader.push_dir(File.join(__dir__, ".."))
|
41
|
+
loader.tag = "sbmt-kafka_consumer"
|
42
|
+
|
43
|
+
# protobuf is an optional dependency
|
44
|
+
loader.do_not_eager_load("#{__dir__}/kafka_consumer/serialization/protobuf_deserializer.rb")
|
45
|
+
loader.do_not_eager_load("#{__dir__}/kafka_consumer/instrumentation/open_telemetry_loader.rb")
|
46
|
+
loader.do_not_eager_load("#{__dir__}/kafka_consumer/instrumentation/open_telemetry_tracer.rb")
|
47
|
+
loader.do_not_eager_load("#{__dir__}/kafka_consumer/instrumentation/sentry_tracer.rb")
|
48
|
+
|
49
|
+
# completely ignore testing helpers
|
50
|
+
# because testing.rb just requires some files and does not contain any constants (e.g. Testing) which Zeitwerk expects
|
51
|
+
loader.ignore("#{__dir__}/kafka_consumer/testing.rb")
|
52
|
+
loader.ignore("#{__dir__}/kafka_consumer/testing")
|
53
|
+
loader.ignore("#{File.expand_path("../", __dir__)}/generators")
|
54
|
+
|
55
|
+
loader.inflector.inflect("cli" => "CLI")
|
56
|
+
loader.inflector.inflect("version" => "VERSION")
|
57
|
+
|
58
|
+
loader.setup
|
59
|
+
loader.eager_load
|
data/rubocop/rspec.yml
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
RSpec/AnyInstance:
|
2
|
+
Enabled: false
|
3
|
+
|
4
|
+
RSpec/MultipleExpectations:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
RSpec/LetSetup:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
RSpec/StubbedMock:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
RSpec/MessageSpies:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
RSpec/NestedGroups:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
RSpec/EmptyExampleGroup:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
RSpec/ExampleLength:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
RSpec/MultipleMemoizedHelpers:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
RSpec/VariableName:
|
29
|
+
Enabled: false
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/sbmt/kafka_consumer/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "sbmt-kafka_consumer"
|
7
|
+
spec.license = "MIT"
|
8
|
+
spec.version = Sbmt::KafkaConsumer::VERSION
|
9
|
+
spec.authors = ["Sbermarket Ruby-Platform Team"]
|
10
|
+
|
11
|
+
spec.summary = "Ruby gem for consuming Kafka messages"
|
12
|
+
spec.description = "This gem is used for consuming Kafka messages. It represents a wrapper over Karafka gem and is recommended for using as a transport with sbmt-outbox"
|
13
|
+
spec.homepage = "https://github.com/SberMarket-Tech/sbmt-kafka_consumer"
|
14
|
+
spec.required_ruby_version = ">= 2.7.0"
|
15
|
+
|
16
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
17
|
+
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
20
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
|
21
|
+
spec.metadata["rubygems_mfa_required"] = "false" # rubocop:disable Gemspec/RequireMFA
|
22
|
+
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
+
spec.files = Dir.chdir(__dir__) do
|
26
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
27
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
spec.bindir = "exe"
|
31
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
32
|
+
spec.require_paths = ["lib"]
|
33
|
+
|
34
|
+
spec.add_dependency "rails", ">= 5.2"
|
35
|
+
spec.add_dependency "zeitwerk", "~> 2.3"
|
36
|
+
spec.add_dependency "karafka", "~> 2.2"
|
37
|
+
spec.add_dependency "yabeda", ">= 0.11"
|
38
|
+
spec.add_dependency "anyway_config", ">= 2.4.0"
|
39
|
+
spec.add_dependency "thor"
|
40
|
+
spec.add_dependency "dry-struct"
|
41
|
+
|
42
|
+
spec.add_development_dependency "appraisal", ">= 2.4"
|
43
|
+
spec.add_development_dependency "bundler", ">= 2.1"
|
44
|
+
spec.add_development_dependency "combustion", ">= 1.3"
|
45
|
+
spec.add_development_dependency "rake", ">= 13.0"
|
46
|
+
spec.add_development_dependency "dry-monads", ">= 1.3"
|
47
|
+
spec.add_development_dependency "factory_bot_rails"
|
48
|
+
spec.add_development_dependency "pg"
|
49
|
+
spec.add_development_dependency "google-protobuf"
|
50
|
+
spec.add_development_dependency "sentry-rails", ">= 5.2"
|
51
|
+
spec.add_development_dependency "opentelemetry-sdk"
|
52
|
+
spec.add_development_dependency "opentelemetry-api", ">= 0.17"
|
53
|
+
spec.add_development_dependency "opentelemetry-common", ">= 0.17"
|
54
|
+
spec.add_development_dependency "opentelemetry-instrumentation-base", ">= 0.17"
|
55
|
+
spec.add_development_dependency "rspec", ">= 3.0"
|
56
|
+
spec.add_development_dependency "rspec_junit_formatter", ">= 0.6"
|
57
|
+
spec.add_development_dependency "rspec-rails", ">= 4.0"
|
58
|
+
spec.add_development_dependency "rubocop-rails", ">= 2.5"
|
59
|
+
spec.add_development_dependency "rubocop-rspec", ">= 2.11"
|
60
|
+
spec.add_development_dependency "sbmt-outbox", ">= 5.0"
|
61
|
+
spec.add_development_dependency "simplecov", ">= 0.16"
|
62
|
+
spec.add_development_dependency "standard", ">= 1.12"
|
63
|
+
|
64
|
+
# let metrics and probes work in dev-mode with combustion
|
65
|
+
# e.g. RAILS_ENV=development bundle exec kafka_consumer
|
66
|
+
spec.add_development_dependency "yabeda-prometheus-mmap"
|
67
|
+
spec.add_development_dependency "webrick"
|
68
|
+
spec.add_development_dependency "rack"
|
69
|
+
spec.add_development_dependency "http_health_check"
|
70
|
+
end
|