kril 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.idea/kril.iml +9 -0
- data/.idea/modules.xml +8 -0
- data/.idea/vcs.xml +6 -0
- data/.idea/workspace.xml +576 -0
- data/.travis.yml +22 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +89 -0
- data/Rakefile +10 -0
- data/bin/kril +79 -0
- data/kril.gemspec +35 -0
- data/lib/kril/consumer.rb +66 -0
- data/lib/kril/producer.rb +30 -0
- data/lib/kril/record_builder.rb +85 -0
- data/lib/kril/schema_extractor.rb +49 -0
- data/lib/kril/version.rb +5 -0
- data/lib/kril.rb +17 -0
- metadata +215 -0
data/.travis.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
language: ruby
|
2
|
+
cache: bundler
|
3
|
+
|
4
|
+
rvm:
|
5
|
+
- 2.4.0
|
6
|
+
|
7
|
+
before_install: gem install bundler -v 1.16.0
|
8
|
+
|
9
|
+
notifications:
|
10
|
+
email:
|
11
|
+
recipients:
|
12
|
+
- chad.bowman0@gmail.com
|
13
|
+
on_failure: change
|
14
|
+
on_success: never
|
15
|
+
|
16
|
+
deploy:
|
17
|
+
provider: pages
|
18
|
+
skip_cleanup: true
|
19
|
+
github_token: $GITHUB_TOKEN
|
20
|
+
project_name: kril
|
21
|
+
on:
|
22
|
+
branch: master
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Chad Bowman
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# Kril 🦐
|
2
|
+
|
3
|
+
Kril is an easy to use command line interface (CLI) for interacting with [Apache Kafka](https://kafka.apache.org/). It uses [Apache Avro](https://avro.apache.org/) for serialization/deserialization.
|
4
|
+
|
5
|
+
[![Build Status](https://travis-ci.org/ChadBowman/kril.svg?branch=master)](https://travis-ci.org/ChadBowman/kril)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemspec:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
spec.add_development_dependency 'kril', '~> 0.1'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install kril
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
Assuming your schema is not registered with the schema registry, and doesn't exist in the repository, you can define a schema and commit a record like so:
|
26
|
+
```bash
|
27
|
+
$ kril --bootstrap-servers 'localhost:9092,localhost:9093,localhost:9094' \
|
28
|
+
--schema-registry 'http://localhost:8081' \
|
29
|
+
--with-schema '{"type":"record","name":"human","fields":[{"name":"age","type":"int"}]}' \
|
30
|
+
--record '{"age": 27}' \
|
31
|
+
human
|
32
|
+
```
|
33
|
+
```bash
|
34
|
+
🦐 saved human: {"type"=>"record", "name"=>"human", "fields"=>[{"name"=>"age", "type"=>"int"}]}
|
35
|
+
🦐 human: {"age"=>27}
|
36
|
+
```
|
37
|
+
|
38
|
+
Now we can consume a single record:
|
39
|
+
```bash
|
40
|
+
$ kril --pretty-print human
|
41
|
+
```
|
42
|
+
```bash
|
43
|
+
🦐 human:
|
44
|
+
{
|
45
|
+
"key": null,
|
46
|
+
"value": {
|
47
|
+
"age": 27
|
48
|
+
},
|
49
|
+
"offset": 0,
|
50
|
+
"create_time": "2018-03-04 00:29:47 -0700",
|
51
|
+
"topic": "human",
|
52
|
+
"partition": 4
|
53
|
+
}
|
54
|
+
```
|
55
|
+
---
|
56
|
+
Now that the schema exists, we can produce records simply:
|
57
|
+
```bash
|
58
|
+
$ kril -r '{"age": 33}' human
|
59
|
+
```
|
60
|
+
```bash
|
61
|
+
🦐 human: {"age"=>33}
|
62
|
+
```
|
63
|
+
---
|
64
|
+
Consuming all records ever:
|
65
|
+
```bash
|
66
|
+
$ kril --consume-all human
|
67
|
+
```
|
68
|
+
```bash
|
69
|
+
🦐 human: {:key=>nil, :value=>{"age"=>27}, :offset=>0, :create_time=>2018-03-04 00:12:32 -0700, :topic=>"human", :partition=>2}
|
70
|
+
🦐 human: {:key=>nil, :value=>{"age"=>27}, :offset=>0, :create_time=>2018-03-04 00:29:47 -0700, :topic=>"human", :partition=>4}
|
71
|
+
🦐 human: {:key=>nil, :value=>{"age"=>27}, :offset=>0, :create_time=>2018-03-04 00:26:33 -0700, :topic=>"human", :partition=>1}
|
72
|
+
🦐 human: {:key=>nil, :value=>{"age"=>27}, :offset=>0, :create_time=>2018-03-04 00:25:54 -0700, :topic=>"human", :partition=>3}
|
73
|
+
🦐 human: {:key=>nil, :value=>{"age"=>33}, :offset=>1, :create_time=>2018-03-04 00:34:07 -0700, :topic=>"human", :partition=>3}
|
74
|
+
🦐 human: {:key=>nil, :value=>{"age"=>27}, :offset=>0, :create_time=>2018-03-04 00:13:13 -0700, :topic=>"human", :partition=>0}
|
75
|
+
```
|
76
|
+
|
77
|
+
## Contributing
|
78
|
+
|
79
|
+
1. Fork it ( https://github.com/ChadBowman/kril/fork )
|
80
|
+
2. Create your feature branch (git checkout -b my-new-feature)
|
81
|
+
3. Commit your changes (git commit -am 'add some feature')
|
82
|
+
4. Push to the branch (git push origin my-new-feature)
|
83
|
+
5. Create a new Pull Request
|
84
|
+
|
85
|
+
Please try to obey [Rubocop](https://github.com/bbatsov/rubocop) to the best of your abilities.
|
86
|
+
|
87
|
+
## License
|
88
|
+
|
89
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
# Default directory to look in is `/specs`
|
5
|
+
# Run with `rake spec`
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
7
|
+
task.rspec_opts = ['--color', '--format documentation']
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => :spec
|
data/bin/kril
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
3
|
+
$VERBOSE = ARGV.map { |arg| true if arg.match?(/-v|--verbose/) }.compact.first
|
4
|
+
|
5
|
+
require 'avro_turf/messaging'
|
6
|
+
require 'kafka'
|
7
|
+
require 'clamp'
|
8
|
+
require 'kril'
|
9
|
+
|
10
|
+
Clamp do
|
11
|
+
option %w[-k --bootstrap-servers], '', 'address(es) of kafka cluster',
|
12
|
+
default: %w[localhost:9092 localhost:9093 localhost:9094] do |address_string|
|
13
|
+
address_string.split(/,\s*/)
|
14
|
+
end
|
15
|
+
# configuration
|
16
|
+
option %w[-g --schema-registry], '', 'address of schema registry', default: 'http://localhost:8081'
|
17
|
+
option %w[-p --schemas-path], '', 'directory of avro schemas', default: 'schemas/'
|
18
|
+
option %w[-v --verbose], :flag, 'print logs, warnings'
|
19
|
+
option %w[-e --pretty-print], :flag, 'pretty print records', default: false
|
20
|
+
|
21
|
+
# producing
|
22
|
+
option %w[-r --record], '', 'record to commit to topic'
|
23
|
+
option %w[-o --syncronous], :flag, 'commit records syncronously', default: false
|
24
|
+
option %w[-w --with-schema], '', 'add schema to respository'
|
25
|
+
|
26
|
+
# consuming
|
27
|
+
option %w[-f --follow], :flag, 'consume from topic indefinitely', defualt: false
|
28
|
+
option %w[-a --consume-all], :flag, 'consume every record on topic', default: false
|
29
|
+
|
30
|
+
parameter 'TOPIC', 'topic to produce to or consume from'
|
31
|
+
parameter '[NAME]', 'schema name'
|
32
|
+
|
33
|
+
def execute
|
34
|
+
if topic
|
35
|
+
log = Logger.new($STDOUT)
|
36
|
+
log.level = verbose? ? Logger::WARN : Logger::ERROR
|
37
|
+
kafka = Kafka.new(bootstrap_servers, logger: log, client_id: 'kril')
|
38
|
+
avro = AvroTurf::Messaging.new(registry_url: schema_registry,
|
39
|
+
schemas_path: schemas_path,
|
40
|
+
logger: log)
|
41
|
+
|
42
|
+
if with_schema
|
43
|
+
schema = JSON.parse(with_schema)
|
44
|
+
schema_name = schema['name']
|
45
|
+
path = File.join(schemas_path, "#{schema_name}.avsc")
|
46
|
+
File.open(path, 'w') { |file| file.write(JSON.pretty_generate(schema)) }
|
47
|
+
print_record("saved #{schema_name}", schema)
|
48
|
+
end
|
49
|
+
|
50
|
+
if record
|
51
|
+
producer = Kril::Producer.new(kafka: kafka, avro: avro)
|
52
|
+
rec = JSON.parse(record)
|
53
|
+
producer.send(record: rec,
|
54
|
+
schema_name: name || topic,
|
55
|
+
topic: topic,
|
56
|
+
syncronous: syncronous?)
|
57
|
+
print_record(topic, rec)
|
58
|
+
else
|
59
|
+
consumer = Kril::Consumer.new(kafka: kafka, avro: avro)
|
60
|
+
if consume_all?
|
61
|
+
consumer.consume_all(topic) do |message|
|
62
|
+
print_record(topic, message)
|
63
|
+
end
|
64
|
+
elsif follow?
|
65
|
+
consumer.listen(topic) do |message|
|
66
|
+
print_record(topic, message)
|
67
|
+
end
|
68
|
+
else
|
69
|
+
print_record(topic, consumer.consume_one(topic))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def print_record(topic, record)
|
76
|
+
record = "\n#{JSON.pretty_generate(record)}" if pretty_print?
|
77
|
+
puts "🦐 #{topic}: #{record}"
|
78
|
+
end
|
79
|
+
end
|
data/kril.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'kril/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'kril'
|
8
|
+
spec.version = Kril::VERSION
|
9
|
+
spec.authors = ['Chad Bowman']
|
10
|
+
spec.email = ['chad.bowman0@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = 'A simple command line tool for interacting with Kafka'
|
13
|
+
spec.description = 'Makes producing and consuming topics simple. Useful when experimenting.'
|
14
|
+
spec.homepage = 'https://github.com/ChadBowman/kril'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
|
21
|
+
spec.bindir = 'bin'
|
22
|
+
spec.executables = ['kril']
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
25
|
+
spec.add_development_dependency 'avro_turf', '~> 0.8.0'
|
26
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
27
|
+
spec.add_development_dependency 'clamp', '~> 1.2', '>= 1.2.1'
|
28
|
+
spec.add_development_dependency 'httparty', '~> 0.16.0'
|
29
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
30
|
+
spec.add_development_dependency 'rspec', '~> 3.7'
|
31
|
+
spec.add_development_dependency 'rspec-nc', '~> 0.3.0'
|
32
|
+
spec.add_development_dependency 'ruby-kafka', '~> 0.5.3'
|
33
|
+
spec.add_development_dependency 'sinatra', '~> 2.0', '>= 2.0.1'
|
34
|
+
spec.add_development_dependency 'webmock', '~> 3.3'
|
35
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kril
|
4
|
+
# Consumers records from Kafka
|
5
|
+
class Consumer
|
6
|
+
def initialize(avro: nil, kafka: nil, config: {})
|
7
|
+
config[:group_id] ||= '🦐'
|
8
|
+
@avro = avro
|
9
|
+
@kafka = kafka
|
10
|
+
@config = config
|
11
|
+
end
|
12
|
+
|
13
|
+
def consume_one(topic)
|
14
|
+
consumer = build_consumer(topic, true, @config)
|
15
|
+
msg = nil
|
16
|
+
consumer.each_message do |message|
|
17
|
+
msg = decode(message)
|
18
|
+
consumer.mark_message_as_processed(message)
|
19
|
+
consumer.commit_offsets
|
20
|
+
consumer.stop
|
21
|
+
end
|
22
|
+
msg
|
23
|
+
ensure
|
24
|
+
consumer.stop
|
25
|
+
end
|
26
|
+
|
27
|
+
def consume_all(topic)
|
28
|
+
config = @config.clone
|
29
|
+
config[:group_id] = SecureRandom.uuid
|
30
|
+
consumer = build_consumer(topic, true, config)
|
31
|
+
consumer.each_message do |message|
|
32
|
+
yield decode(message), consumer
|
33
|
+
end
|
34
|
+
ensure
|
35
|
+
consumer.stop
|
36
|
+
end
|
37
|
+
|
38
|
+
def listen(topic)
|
39
|
+
consumer = build_consumer(topic, false, @config)
|
40
|
+
consumer.each_message do |message|
|
41
|
+
yield decode(message), consumer
|
42
|
+
end
|
43
|
+
ensure
|
44
|
+
consumer.stop
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def build_consumer(topic, start_from_beginning, config)
|
50
|
+
consumer = @kafka.consumer(config)
|
51
|
+
consumer.subscribe(topic, start_from_beginning: start_from_beginning)
|
52
|
+
consumer
|
53
|
+
end
|
54
|
+
|
55
|
+
def decode(message)
|
56
|
+
{
|
57
|
+
key: message.key,
|
58
|
+
value: @avro.decode(message.value),
|
59
|
+
offset: message.offset,
|
60
|
+
create_time: message.create_time,
|
61
|
+
topic: message.topic,
|
62
|
+
partition: message.partition
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kril
|
4
|
+
# Produces records to Kafka
|
5
|
+
class Producer
|
6
|
+
def initialize(avro: nil, kafka: nil, config: {})
|
7
|
+
config[:required_acks] ||= 1
|
8
|
+
config[:delivery_threshold] ||= 1
|
9
|
+
sync_config = config.dup
|
10
|
+
@avro = avro
|
11
|
+
@async = kafka.async_producer(config)
|
12
|
+
sync_config.delete(:delivery_threshold)
|
13
|
+
@sync = kafka.producer(sync_config)
|
14
|
+
end
|
15
|
+
|
16
|
+
def send(record:, schema_name:, topic: nil, syncronous: false)
|
17
|
+
topic ||= schema_name
|
18
|
+
encoded = @avro.encode(record, schema_name: schema_name)
|
19
|
+
if syncronous
|
20
|
+
@producer.produce(encoded, topic: topic)
|
21
|
+
@producer.deliver_messages
|
22
|
+
else
|
23
|
+
@async.produce(encoded, topic: topic)
|
24
|
+
end
|
25
|
+
ensure
|
26
|
+
@async.shutdown
|
27
|
+
@sync.shutdown
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kril
|
4
|
+
# Creates and validates a record based from a defined schema.
|
5
|
+
class RecordBuilder
|
6
|
+
def initialize(schema_file_name: nil,
|
7
|
+
schemas_dir: 'schemas',
|
8
|
+
schema_path: nil)
|
9
|
+
path = schema_path || File.join(schemas_dir, "#{schema_file_name}.avsc")
|
10
|
+
file = File.read(path)
|
11
|
+
@schema = JSON.parse(file)
|
12
|
+
end
|
13
|
+
|
14
|
+
def build(data)
|
15
|
+
data = JSON.parse(data)
|
16
|
+
build_from_record(@schema, data)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def build_from_record(schema, data)
|
22
|
+
schema['fields'].each_with_object({}) do |field, record|
|
23
|
+
field_name = field['name']
|
24
|
+
record[field_name] =
|
25
|
+
case field['type']
|
26
|
+
when 'array'
|
27
|
+
build_from_array(field, data[field_name])
|
28
|
+
when 'map'
|
29
|
+
build_from_map(field, data[field_name])
|
30
|
+
when 'record'
|
31
|
+
build_from_record(field, data[field_name])
|
32
|
+
else
|
33
|
+
build_field(field, data[field_name])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def build_from_array(field, data)
|
39
|
+
data.map { |element| build_field(field, element) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_from_map(field, data)
|
43
|
+
data.transform_values { |element| build_field(field, element) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def build_field(field, datum)
|
47
|
+
check_nullity(datum, field)
|
48
|
+
type = field['items'] || field['values'] || field['type']
|
49
|
+
convert_type(datum, type)
|
50
|
+
end
|
51
|
+
|
52
|
+
def check_nullity(datum, field)
|
53
|
+
type = field['values'] || field['items'] || field['type']
|
54
|
+
unless datum || type&.include?('null')
|
55
|
+
raise ArgumentError.new, "Input for #{field['name']} cannot be nil"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def convert_type(datum, type)
|
60
|
+
type = gather_types(type)
|
61
|
+
if datum.nil?
|
62
|
+
nil
|
63
|
+
elsif type.include?('int') || type.include?('long')
|
64
|
+
datum.to_i
|
65
|
+
elsif type.include?('float') || type.include?('double')
|
66
|
+
datum.to_f
|
67
|
+
elsif type.include?('boolean')
|
68
|
+
datum.casecmp('true').zero?
|
69
|
+
else
|
70
|
+
datum
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def gather_types(type)
|
75
|
+
case type
|
76
|
+
when String
|
77
|
+
type
|
78
|
+
when Array
|
79
|
+
type.flat_map { |t| gather_types(t) }
|
80
|
+
when Hash
|
81
|
+
gather_types(type['type'])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kril
|
4
|
+
# Extracts avro schemas from avro genrated java files.
|
5
|
+
class SchemaExtractor
|
6
|
+
def initialize(source_dir:, output_dir:)
|
7
|
+
@source_dir = File.join(Dir.pwd, source_dir)
|
8
|
+
@output_dir = File.join(Dir.pwd, output_dir)
|
9
|
+
end
|
10
|
+
|
11
|
+
def extract
|
12
|
+
find_java_files(@source_dir) do |file|
|
13
|
+
schema = parse_avro_java_class(file)
|
14
|
+
write_avsc(schema, @output_dir) if schema
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def find_java_files(root_dir)
|
21
|
+
old_dir = Dir.pwd
|
22
|
+
Dir.chdir(root_dir)
|
23
|
+
java_files = File.join('**', '*.java')
|
24
|
+
Dir.glob(java_files) do |file|
|
25
|
+
yield File.new(file)
|
26
|
+
end
|
27
|
+
Dir.chdir(old_dir)
|
28
|
+
end
|
29
|
+
|
30
|
+
def write_avsc(contents, directory)
|
31
|
+
path = File.join(directory, "#{contents['name']}.avsc")
|
32
|
+
File.open(path, 'w') do |file|
|
33
|
+
file.write(JSON.pretty_generate(contents))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def dejavafy(java_string)
|
38
|
+
java_string.split('","').join.gsub(/\\?\\"/, '"')
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse_avro_java_class(file)
|
42
|
+
file.each_line do |line|
|
43
|
+
extraction = line[/SCHEMA.*parse\("(.*)"\);/, 1]
|
44
|
+
break JSON.parse(dejavafy(extraction)) if extraction
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/kril/version.rb
ADDED
data/lib/kril.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kril/version'
|
4
|
+
require 'kril/record_builder'
|
5
|
+
require 'kril/schema_extractor'
|
6
|
+
require 'kril/producer'
|
7
|
+
require 'kril/consumer'
|
8
|
+
require 'json'
|
9
|
+
require 'yaml'
|
10
|
+
require 'logger'
|
11
|
+
require 'avro_turf/messaging'
|
12
|
+
require 'kafka'
|
13
|
+
require 'securerandom'
|
14
|
+
|
15
|
+
# TODO
|
16
|
+
module Kril
|
17
|
+
end
|