bps-kafka 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.
- checksums.yaml +7 -0
- data/bps-kafka.gemspec +22 -0
- data/lib/bps-kafka.rb +1 -0
- data/lib/bps/kafka.rb +18 -0
- data/lib/bps/publisher/kafka.rb +102 -0
- data/lib/bps/publisher/kafka_async.rb +37 -0
- data/spec/bps/kafka_spec.rb +38 -0
- metadata +77 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5c35677b45d9df97c7ab28ef3ce4e910d2edcd6def70caa235923b48ab9cd057
|
4
|
+
data.tar.gz: 5d4ee5dce8765945dd11a373e4d461e1c5aaf08ee32e77f7e40c64954d934f2e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: be7fcda9c77f2f3bb4d29f49bb29ecce4362f0bd41405e6567b93f9ce4c81019e522d3d7bfecb81d52e67d468bbc8e807c562d35cac8a05f1cf01d03d0a7eb61
|
7
|
+
data.tar.gz: af85befa5ff134a58df21d247b648b72d2c81206ffe1613c92ae8270d43bcb3ba3d12e9adcd31f3832ff0c2966d04e2ae377f93d5a3c8ff348a360e70f0021a5
|
data/bps-kafka.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'bps-kafka'
|
3
|
+
s.version = File.read(File.expand_path('../../.version', __dir__)).strip
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
|
6
|
+
s.licenses = ['Apache-2.0']
|
7
|
+
s.summary = 'Kafka adapter for bps'
|
8
|
+
s.description = 'https://github.com/bsm/bps'
|
9
|
+
|
10
|
+
s.authors = ['Black Square Media']
|
11
|
+
s.email = 'info@blacksquaremedia.com'
|
12
|
+
s.homepage = 'https://github.com/bsm/bps'
|
13
|
+
|
14
|
+
s.executables = []
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
s.required_ruby_version = '>= 2.6.0'
|
19
|
+
|
20
|
+
s.add_dependency 'bps', s.version
|
21
|
+
s.add_dependency 'ruby-kafka', '>= 1.1.0.beta1'
|
22
|
+
end
|
data/lib/bps-kafka.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bps/kafka'
|
data/lib/bps/kafka.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'bps'
|
2
|
+
require 'kafka'
|
3
|
+
require 'bps/publisher/kafka'
|
4
|
+
require 'bps/publisher/kafka_async'
|
5
|
+
|
6
|
+
module BPS
|
7
|
+
module Publisher
|
8
|
+
register('kafka+sync') do |url, **opts|
|
9
|
+
addrs = CGI.unescape(url.host).split(',')
|
10
|
+
Kafka.new(addrs, **Kafka.coercer.coerce(opts))
|
11
|
+
end
|
12
|
+
|
13
|
+
register('kafka') do |url, **opts|
|
14
|
+
addrs = CGI.unescape(url.host).split(',')
|
15
|
+
KafkaAsync.new(addrs, **Kafka.coercer.coerce(opts))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'bps/kafka'
|
2
|
+
|
3
|
+
module BPS
|
4
|
+
module Publisher
|
5
|
+
class Kafka < Abstract
|
6
|
+
class Topic
|
7
|
+
def initialize(producer, topic)
|
8
|
+
@producer = producer
|
9
|
+
@topic = topic
|
10
|
+
end
|
11
|
+
|
12
|
+
def publish(message, **opts)
|
13
|
+
@producer.produce(message, **opts, topic: @topic)
|
14
|
+
after_publish
|
15
|
+
end
|
16
|
+
|
17
|
+
def flush
|
18
|
+
@producer.deliver_messages
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def after_publish
|
24
|
+
@producer.deliver_messages
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
CLIENT_OPTS = {
|
30
|
+
client_id: :string,
|
31
|
+
connect_timeout: :float,
|
32
|
+
socket_timeout: :float,
|
33
|
+
ssl_ca_cert_file_path: :string,
|
34
|
+
ssl_ca_cert: :string,
|
35
|
+
ssl_client_cert: :string,
|
36
|
+
ssl_client_cert_key: :string,
|
37
|
+
ssl_client_cert_key_password: :string,
|
38
|
+
ssl_client_cert_chain: :string,
|
39
|
+
sasl_gssapi_principal: :string,
|
40
|
+
sasl_gssapi_keytab: :string,
|
41
|
+
sasl_plain_authzid: :string,
|
42
|
+
sasl_plain_username: :string,
|
43
|
+
sasl_plain_password: :string,
|
44
|
+
sasl_scram_username: :string,
|
45
|
+
sasl_scram_password: :string,
|
46
|
+
sasl_scram_mechanism: :string,
|
47
|
+
sasl_over_ssl: :bool,
|
48
|
+
ssl_ca_certs_from_system: :bool,
|
49
|
+
ssl_verify_hostname: :bool,
|
50
|
+
}.freeze
|
51
|
+
|
52
|
+
PRODUCER_OPTS = {
|
53
|
+
# standard
|
54
|
+
retry_backoff: :float,
|
55
|
+
compression_codec: :symbol,
|
56
|
+
compression_threshold: :int,
|
57
|
+
ack_timeout: :float,
|
58
|
+
required_acks: :symbol,
|
59
|
+
max_retries: :int,
|
60
|
+
max_buffer_size: :int,
|
61
|
+
max_buffer_bytesize: :int,
|
62
|
+
idempotent: :bool,
|
63
|
+
transactional: :bool,
|
64
|
+
transactional_id: :string,
|
65
|
+
transactional_timeout: :bool,
|
66
|
+
# async
|
67
|
+
delivery_interval: :float,
|
68
|
+
delivery_threshold: :int,
|
69
|
+
max_queue_size: :int,
|
70
|
+
}.freeze
|
71
|
+
|
72
|
+
# @return [BPS::Coercer] the options coercer.
|
73
|
+
def self.coercer
|
74
|
+
@coercer ||= BPS::Coercer.new(CLIENT_OPTS.merge(PRODUCER_OPTS)).freeze
|
75
|
+
end
|
76
|
+
|
77
|
+
# @param [Array<String>] brokers the seed broker addresses.
|
78
|
+
# @param [Hash] opts the options.
|
79
|
+
# @see https://www.rubydoc.info/gems/ruby-kafka/Kafka/Client#initialize-instance_method
|
80
|
+
def initialize(broker_addrs, **opts)
|
81
|
+
@topics = {}
|
82
|
+
@client = ::Kafka.new(broker_addrs, **opts.slice(*CLIENT_OPTS.keys))
|
83
|
+
@producer = init_producer(**opts.slice(*PRODUCER_OPTS.keys))
|
84
|
+
end
|
85
|
+
|
86
|
+
def topic(name)
|
87
|
+
@topics[name] ||= self.class::Topic.new(@producer, name)
|
88
|
+
end
|
89
|
+
|
90
|
+
def close
|
91
|
+
@producer.shutdown
|
92
|
+
@client.close
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def init_producer(**opts)
|
98
|
+
@producer = @client.producer(**opts)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'bps/publisher/kafka'
|
2
|
+
|
3
|
+
module BPS
|
4
|
+
module Publisher
|
5
|
+
class KafkaAsync < Kafka
|
6
|
+
class Topic < Kafka::Topic
|
7
|
+
private
|
8
|
+
|
9
|
+
def after_publish; end
|
10
|
+
end
|
11
|
+
|
12
|
+
# @see BPS::Kafka::Publisher
|
13
|
+
#
|
14
|
+
# @param [Hash] opts the options.
|
15
|
+
# @option opts [Integer] :max_queue_size (defaults to: 1000)
|
16
|
+
# the maximum number of messages allowed in the queue.
|
17
|
+
# @option opts [Integer] :delivery_threshold (defaults to: 0)
|
18
|
+
# if greater than zero, the number of buffered messages that will automatically
|
19
|
+
# trigger a delivery.
|
20
|
+
# @option opts [Integer] :delivery_interval (defaults to: 0) if greater than zero, the number of
|
21
|
+
# seconds between automatic message deliveries.
|
22
|
+
def initialize(broker_addrs, **opts)
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def init_producer(max_queue_size: 1000, delivery_threshold: 0, delivery_interval: 0)
|
29
|
+
@client.async_producer(
|
30
|
+
max_queue_size: max_queue_size,
|
31
|
+
delivery_threshold: delivery_threshold,
|
32
|
+
delivery_interval: delivery_interval,
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bps/kafka'
|
3
|
+
|
4
|
+
def kafka_addrs
|
5
|
+
ENV.fetch('KAFKA_ADDRS', '127.0.0.1:9092').split(',').freeze
|
6
|
+
end
|
7
|
+
|
8
|
+
run_spec = \
|
9
|
+
begin
|
10
|
+
::Kafka.new(kafka_addrs).brokers
|
11
|
+
true
|
12
|
+
rescue StandardError => e
|
13
|
+
warn "WARNING: unable to run #{File.basename __FILE__}: #{e.message}"
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
helper = proc do
|
18
|
+
def read_messages(topic_name, num_messages)
|
19
|
+
client = ::Kafka.new(kafka_addrs)
|
20
|
+
Enumerator.new do |y|
|
21
|
+
client.each_message(topic: topic_name, start_from_beginning: true) do |msg|
|
22
|
+
y << msg.value
|
23
|
+
end
|
24
|
+
end.take(num_messages)
|
25
|
+
ensure
|
26
|
+
client&.close
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
RSpec.describe 'Kafka', if: run_spec do
|
31
|
+
context BPS::Publisher::Kafka do
|
32
|
+
it_behaves_like 'publisher', url: "kafka+sync://#{kafka_addrs.join(',')}/", &helper
|
33
|
+
end
|
34
|
+
|
35
|
+
context BPS::Publisher::KafkaAsync do
|
36
|
+
it_behaves_like 'publisher', url: "kafka://#{kafka_addrs.join(',')}/", &helper
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bps-kafka
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Black Square Media
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-07-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bps
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.0.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.0.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ruby-kafka
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.1.0.beta1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.1.0.beta1
|
41
|
+
description: https://github.com/bsm/bps
|
42
|
+
email: info@blacksquaremedia.com
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- bps-kafka.gemspec
|
48
|
+
- lib/bps-kafka.rb
|
49
|
+
- lib/bps/kafka.rb
|
50
|
+
- lib/bps/publisher/kafka.rb
|
51
|
+
- lib/bps/publisher/kafka_async.rb
|
52
|
+
- spec/bps/kafka_spec.rb
|
53
|
+
homepage: https://github.com/bsm/bps
|
54
|
+
licenses:
|
55
|
+
- Apache-2.0
|
56
|
+
metadata: {}
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 2.6.0
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubygems_version: 3.1.4
|
73
|
+
signing_key:
|
74
|
+
specification_version: 4
|
75
|
+
summary: Kafka adapter for bps
|
76
|
+
test_files:
|
77
|
+
- spec/bps/kafka_spec.rb
|