flipp-ruby-kafka-temp-fork 0.0.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.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +97 -0
  3. data/.dockerignore +2 -0
  4. data/.gitignore +41 -0
  5. data/.gitmodules +0 -0
  6. data/.rspec +1 -0
  7. data/.rubocop.yml +56 -0
  8. data/.ruby-gemset +1 -0
  9. data/.ruby-version +1 -0
  10. data/CHANGELOG.md +466 -0
  11. data/Dockerfile +21 -0
  12. data/Gemfile +6 -0
  13. data/Gemfile.lock +207 -0
  14. data/Guardfile +22 -0
  15. data/README.md +102 -0
  16. data/Rakefile +13 -0
  17. data/bin/flipp_ruby_kafka +4 -0
  18. data/deploy/artifactory.sh +8 -0
  19. data/deploy/config.json +4 -0
  20. data/docker-compose.yml +89 -0
  21. data/docs/UPGRADE_1.0.md +39 -0
  22. data/flipp-ruby-kafka.gemspec +34 -0
  23. data/kafkateria/factories/my_schema.rb +16 -0
  24. data/kafkateria/factories/my_schema_with_id.rb +16 -0
  25. data/lib/flipp_ruby_kafka.rb +73 -0
  26. data/lib/flipp_ruby_kafka/flipp_datadog_metrics.rb +15 -0
  27. data/lib/flipp_ruby_kafka/test_helpers.rb +59 -0
  28. data/lib/flipp_ruby_kafka/utils/platform_schema_validation.rb +77 -0
  29. data/lib/flipp_ruby_kafka/utils/platform_topic_validation.rb +41 -0
  30. data/lib/flipp_ruby_kafka/version.rb +5 -0
  31. data/lib/generators/flipp_ruby_kafka/schema_validation/schema_validation_generator.rb +23 -0
  32. data/lib/generators/flipp_ruby_kafka/topic_validation/topic_validation_generator.rb +22 -0
  33. data/spec/flipp_ruby_kafka_spec.rb +8 -0
  34. data/spec/integration/send_kafka_spec.rb +63 -0
  35. data/spec/phobos.yml +73 -0
  36. data/spec/schemas/com/my-namespace/MySchema-key.avsc +13 -0
  37. data/spec/schemas/com/my-namespace/MySchema.avsc +18 -0
  38. data/spec/schemas/com/my-namespace/MySchemaWithDateTimes.avsc +33 -0
  39. data/spec/schemas/com/my-namespace/MySchemaWithId.avsc +28 -0
  40. data/spec/spec_helper.rb +39 -0
  41. data/spec/utils/platform_schema_validation_spec.rb +54 -0
  42. data/spec/utils/platform_topic_validation_spec.rb +50 -0
  43. metadata +262 -0
@@ -0,0 +1,39 @@
1
+ # Upgrading to v2.0
2
+
3
+ The following breaking changes were introduced in version 1.0:
4
+
5
+ * Lag reporting is now optional, and controlled by `config.report_lag`. To
6
+ re-enable it, you must set `config.report_lag` to true. We recommend you
7
+ only set this to true on production or staging environments and not
8
+ development or test.
9
+ * Topics that have no keys now must use `key_config none: true` instead
10
+ of `key_config plain: true`.
11
+ * `KafkaPublishFailure` has been removed - any code that relies on it must
12
+ likewise be removed, and the database table can also be dropped. You can
13
+ also remove any reference to the `payloads_for_resend` method defined
14
+ on your producers.
15
+ * Its replacement is the new `db` [publish backend](../README.md#database-backend).
16
+ Note that to use this option, you need to have [activerecord-import](https://github.com/zdennis/activerecord-import)
17
+ in your Gemfile.
18
+ * `KafkaSource` will now send messages inside a transaction rather than
19
+ after a commit. Any code (e.g. RSpecs) that relies on the previous
20
+ behavior must be modified.
21
+ * `TestHelpers` no longer automatically stub producers and consumers, to aid
22
+ in the integration testing scenario. Instead, you should add a `before(:each)`
23
+ hook that calls `stub_producers_and_consumers!` Along with this, the
24
+ `kafka_integration` metadata key that used to check for this behavior
25
+ is no longer supported or needed, and can be removed from any tests that
26
+ use it. This allows for more flexibility and explicitness
27
+ in how to determine if tests are integration tests.
28
+ * The `PlatformSchemaValidation` class has moved to the `Utils` module, so
29
+ it is now `FlippRubyKafka::Utils::PlatformSchemaValidation`.
30
+
31
+ Additional changes introduced in v2.0 (which uses Deimos under the hood):
32
+
33
+ * Removed the `sync_produce` option as it's now redundant with the
34
+ `publish_backend` option. `publish_backend` can be set to either
35
+ `:kafka` or `:kafka_async` to reproduce this option.
36
+ * Changed the name of `rake phobos:start` to `rake deimos:start`.
37
+ * Configuration is now mostly handled by flipp-ruby-kafka, including
38
+ defaults for the MS platform. See README for how configuration should
39
+ look now.
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'flipp_ruby_kafka/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'flipp-ruby-kafka-temp-fork'
9
+ spec.version = FlippRubyKafka::VERSION
10
+ spec.authors = ['Daniel Orner']
11
+ spec.email = ['daniel.orner@wishabi.com']
12
+ spec.summary = 'Flipp Kafka libraries for Ruby.'
13
+ spec.description = 'Write a longer description. Optional.'
14
+ spec.homepage = ''
15
+
16
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_runtime_dependency('ddtrace', '>= 0.11')
22
+ spec.add_runtime_dependency('deimos-temp-fork', '>= 0.0.2')
23
+ spec.add_runtime_dependency('flipp-ruby-dogstatsd', '~> 1.0')
24
+ spec.add_runtime_dependency('railties', '>= 3')
25
+
26
+ spec.add_development_dependency('flipp_ruby_style')
27
+ spec.add_development_dependency('guard', '~> 2')
28
+ spec.add_development_dependency('guard-rspec', '~> 4')
29
+ spec.add_development_dependency('guard-rubocop', '~> 1')
30
+ spec.add_development_dependency('rspec', '~> 3')
31
+ spec.add_development_dependency('rspec_junit_formatter', '~>0.3')
32
+ spec.add_development_dependency('rubocop', '~> 0.58')
33
+ spec.add_development_dependency('rubocop-rspec', '~> 1.27')
34
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.define do
4
+ factory :myschema, parent: :base do
5
+ topic { 'my_consume_topic' }
6
+ schema { 'MySchema' }
7
+ namespace { 'com.my-namespace' }
8
+ key_config { { plain: true } }
9
+ fields do
10
+ {
11
+ test_id: -> { Faker::Name.name },
12
+ some_int: -> { Faker::Number.number(5) }
13
+ }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.define do
4
+ factory :myschemawithid, parent: :base do
5
+ topic { 'my_consume_topic_with_id' }
6
+ schema { 'MySchemaWithId' }
7
+ namespace { 'com.my-namespace' }
8
+ key_config { { schema: 'MySchema-key' } }
9
+ fields do
10
+ {
11
+ test_id: -> { Faker::Name.name },
12
+ some_int: -> { Faker::Number.number(5) }
13
+ }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'deimos'
4
+ require 'deimos/tracing/datadog'
5
+ require 'flipp-ruby-dogstatsd'
6
+ require 'rails'
7
+
8
+ # alias all the Deimos stuff
9
+ FlippRubyKafka = Deimos
10
+
11
+ require 'flipp_ruby_kafka/version'
12
+ require 'flipp_ruby_kafka/utils/platform_schema_validation'
13
+ require 'flipp_ruby_kafka/utils/platform_topic_validation'
14
+ require 'flipp_ruby_kafka/flipp_datadog_metrics'
15
+ require 'generators/flipp_ruby_kafka/topic_validation/topic_validation_generator'
16
+ require 'generators/flipp_ruby_kafka/schema_validation/schema_validation_generator'
17
+
18
+ # Parent module.
19
+ module FlippRubyKafka
20
+ after_configure do
21
+ formatter = self.config.logger.formatter
22
+ phobos_formatter = self.config.phobos_logger.formatter.clone
23
+ kafka_formatter = self.config.kafka.logger.formatter.clone
24
+
25
+ if formatter&.respond_to?(:push_global_tags) # FlippRailsLogger
26
+ self.config.phobos_logger.formatter = phobos_formatter
27
+ self.config.kafka.logger.formatter = kafka_formatter
28
+ formatter.push_global_tags('Deimos') unless formatter.current_tags.include?('Deimos')
29
+ end
30
+ if phobos_formatter&.respond_to?(:push_global_tags)
31
+ phobos_formatter.push_global_tags('Phobos') unless phobos_formatter.current_tags.include?('Phobos')
32
+ end
33
+ if kafka_formatter&.respond_to?(:push_global_tags)
34
+ kafka_formatter.push_global_tags('RubyKafka') unless kafka_formatter.current_tags.include?('RubyKafka')
35
+ end
36
+ end
37
+
38
+ define_settings do
39
+ setting :logger, default_proc: proc { Rails.logger.clone }
40
+ setting :schema do
41
+ setting :backend, default_proc: proc { Rails.env.development? ? :avro_validation : :avro_schema_registry }
42
+ setting :path, default_proc: proc { "#{Rails.root}/app/schemas" }
43
+ setting :registry_url, ENV['KAFKA_SCHEMA_REGISTRY'] || 'http://127.0.0.1:8081'
44
+ end
45
+ setting :consumers do
46
+ setting :report_lag, default_proc: proc { !%w(test development).include?(Rails.env) }
47
+ setting(:fatal_error, proc { defined?(ActiveRecord) && !ActiveRecord::Base.connection.active? })
48
+ end
49
+ setting :kafka do
50
+ setting :seed_brokers, ENV['KAFKA_SSL_BROKERS'] || '127.0.0.1:9092'
51
+ setting :ssl do
52
+ setting :enabled, default_proc: proc { !%w(test development).include?(Rails.env) }
53
+ setting :ca_cert, '/var/certs/kafka-broker-ca-public-cert'
54
+ setting :client_cert, '/var/certs/kafka-client-public-key'
55
+ setting :client_cert_key, '/var/certs/kafka-client-private-key-decrypted'
56
+ setting :verify_hostname, false
57
+ end
58
+ end
59
+
60
+ # Base URL for Kafkateria - typically something like localhost:3000
61
+ # for local testing or kafkateria:3000 for docker-compose.
62
+ setting :kafkateria_url, 'http://127.0.0.1:3000'
63
+ end
64
+
65
+ class << self
66
+ # Configure datadog. Must be called after FlippDatadog is configured.
67
+ def configure_datadog
68
+ service_name = "#{FlippDatadog.config&.service || 'frk'}-consumer"
69
+ self.config.metrics = FlippRubyKafka::FlippDatadogMetrics.new(nil, self.config.logger)
70
+ self.config.tracer = Deimos::Tracing::Datadog.new(service_name: service_name)
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'flipp-ruby-dogstatsd'
4
+ require 'deimos/metrics/datadog'
5
+
6
+ module FlippRubyKafka
7
+ # Datadog metrics provider that uses the FlippDatadog gem.
8
+ # Configuration must happen before FlippRubyKafka is configured.
9
+ class FlippDatadogMetrics < Deimos::Metrics::Datadog
10
+ # :nodoc:
11
+ def initialize(_config, _logger)
12
+ @client = FlippDatadog.client
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'deimos/test_helpers'
4
+ FlippRubyKafka = Deimos # in case this is being included directly
5
+
6
+ module FlippRubyKafka
7
+ # :nodoc:
8
+ module TestHelpers
9
+ # Use Kafkateria to clear a topic.
10
+ # @param topic [String]
11
+ def kafkateria_delete_topic(topic)
12
+ base = FlippRubyKafka.config.kafkateria_url
13
+ uri = URI("#{base}/v1/topics/delete_topic?topic=#{topic}")
14
+ request = Net::HTTP::Post.new(uri)
15
+ http = Net::HTTP.new(uri.host, uri.port)
16
+ http.request(request)
17
+ end
18
+
19
+ # Use Kafkateria to generate and produce messages.
20
+ # @param topic [String]
21
+ # @param num_messages [Integer]
22
+ # @param traits [Array<Symbol>]
23
+ # @param values [Hash]
24
+ def kafkateria_produce_messages(topic:, num_messages: 1, traits: [], trait_params: {}, values: {}, null_payload: false, key: nil)
25
+ base = FlippRubyKafka.config.kafkateria_url
26
+ uri = URI("#{base}//v1/messages/generate_and_publish")
27
+ req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
28
+ req.body = { topic: topic, values: values,
29
+ traits: traits, trait_params: trait_params, num_messages: num_messages, null_payload: null_payload, key: key }.to_json
30
+ response = Net::HTTP.start(uri.hostname, uri.port) do |http|
31
+ http.request(req)
32
+ end
33
+ if response.code.to_s != '200'
34
+ raise "Failed #{response.code} producing messages to #{topic}: #{response.body}"
35
+ end
36
+
37
+ JSON.parse(response.body || [])
38
+ end
39
+
40
+ # @param topic [String]
41
+ # @param num_messages [Integer]
42
+ # @return [Array<Hash>] with :key and :payload keys
43
+ def kafkateria_get_messages(topic:, num_messages: 10)
44
+ base = FlippRubyKafka.config.kafkateria_url
45
+ uri = URI("#{base}//v1/messages?topic=#{topic}&num_messages=#{num_messages}")
46
+ res = Net::HTTP.get_response(uri)
47
+ if res.code.to_s != '200'
48
+ raise "Failed #{res.code} getting messages from #{topic}: #{res.body}"
49
+ end
50
+
51
+ response = JSON.parse(res.body)
52
+ if response['payloads'].present?
53
+ response['payloads'].map(&:with_indifferent_access)
54
+ else
55
+ response
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module FlippRubyKafka
6
+ module Utils
7
+ # Generates the Microservice Platform schema validation file.
8
+ # Run this before committing schema changes (or include it in your CircleCI
9
+ # config if you don't mind having to build the same image multiple times).
10
+ # Run this using `rails runner` or in Rails console if you're using Rails.
11
+ class PlatformSchemaValidation
12
+ # @param base_path [String] Set this to Rails.root if running Rails.
13
+ def initialize(base_path: '')
14
+ @base_path ||= FlippRubyKafka.config.schema.path.gsub(%r{^#{base_path}\/}, '')
15
+ end
16
+
17
+ # @param klass [Class < FlippRubyKafka::Producer]
18
+ # @return [Hash]
19
+ def process_producer(klass)
20
+ schema = klass.config[:schema]
21
+ topic = klass.config[:topic]
22
+ return if topic.blank?
23
+
24
+ namespace = klass.config[:namespace] || FlippRubyKafka.config.producers.schema_namespace
25
+ path = namespace.tr('.', '/')
26
+ {
27
+ 'file' => File.join(@base_path, path, "#{schema}.avsc"),
28
+ 'subject' => "#{topic}-value"
29
+ }
30
+ end
31
+
32
+ # @param hash [Hash]
33
+ # @return [Hash]
34
+ def process_consumer(hash)
35
+ klass = hash['handler'].constantize
36
+ topic = hash['topic']
37
+ schema = klass.config[:schema]
38
+ return if schema.blank?
39
+
40
+ namespace = klass.config[:namespace] || ''
41
+ path = namespace.tr('.', '/')
42
+ {
43
+ 'file' => File.join(@base_path, path, "#{schema}.avsc"),
44
+ 'subject' => "#{topic}-value"
45
+ }
46
+ end
47
+
48
+ # @return [String]
49
+ def generate_config
50
+ @full_config = []
51
+ FlippRubyKafka::Producer.descendants.each do |klass|
52
+ next if klass.topic.blank?
53
+
54
+ config = process_producer(klass)
55
+ @full_config << config if config
56
+ end
57
+
58
+ Phobos.config['listeners'].each do |h|
59
+ config = process_consumer(h)
60
+ @full_config << config if config
61
+ end
62
+
63
+ {
64
+ environments: {
65
+ default: @full_config
66
+ }
67
+ }
68
+ end
69
+
70
+ # :nodoc:
71
+ def run
72
+ full_json = generate_config
73
+ File.write('schema-validation.json', JSON.pretty_generate(full_json))
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module FlippRubyKafka
6
+ module Utils
7
+ # Generates the Microservice Platform topic validation file.
8
+ # Use rake flipp_ruby_kafka:topic_validation my_service to run it from command line.
9
+ class PlatformTopicValidation
10
+ class << self
11
+ # @param service_name [String]
12
+ def save_config_to_file(service_name)
13
+ config = generate_config(service_name)
14
+ File.open("#{Rails.root}/topic-validation.json", 'w') do |f|
15
+ f.write(config.to_json)
16
+ end
17
+ end
18
+
19
+ # @param service_name [String]
20
+ # @return [Hash]
21
+ def generate_config(service_name)
22
+ acls = []
23
+ Deimos.config.producer_objects.each do |k|
24
+ next if k.topic.blank?
25
+
26
+ acls.push(topic: k.topic, role: 'producer')
27
+ end
28
+ Deimos.config.consumer_objects.each do |k|
29
+ next if k.topic.blank?
30
+
31
+ acls.push(topic: k.topic, role: 'consumer')
32
+ end
33
+ {
34
+ service: service_name,
35
+ acls: acls
36
+ }
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlippRubyKafka
4
+ VERSION = '0.0.1'
5
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'flipp_ruby_kafka/utils/platform_schema_validation'
5
+
6
+ module FlippRubyKafka
7
+ module Generators
8
+ # Generate the database backend migration.
9
+ class SchemaValidationGenerator < Rails::Generators::Base
10
+ desc 'Generate schema validation config file'
11
+
12
+ # :nodoc:
13
+ def self.namespace
14
+ 'flipp_ruby_kafka:schema_validation'
15
+ end
16
+
17
+ # Main method to create all the necessary files
18
+ def generate
19
+ FlippRubyKafka::Utils::PlatformSchemaValidation.new(base_path: Rails.root).run
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ module FlippRubyKafka
6
+ module Generators
7
+ # Generate the database backend migration.
8
+ class TopicValidationGenerator < Rails::Generators::NamedBase
9
+ desc 'Generate topic validation config file'
10
+
11
+ # :nodoc:
12
+ def self.namespace
13
+ 'flipp_ruby_kafka:topic_validation'
14
+ end
15
+
16
+ # Main method to create all the necessary files
17
+ def generate
18
+ FlippRubyKafka::Utils::PlatformTopicValidation.save_config_to_file(name)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe FlippRubyKafka do
4
+
5
+ it 'should have a version number' do
6
+ expect(FlippRubyKafka::VERSION).not_to be_nil
7
+ end
8
+ end