rafka 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1 -0
- data/README.md +73 -0
- data/lib/rafka.rb +18 -0
- data/lib/rafka/consumer.rb +75 -0
- data/lib/rafka/errors.rb +14 -0
- data/lib/rafka/generic_commands.rb +14 -0
- data/lib/rafka/message.rb +17 -0
- data/lib/rafka/producer.rb +49 -0
- data/lib/rafka/version.rb +3 -0
- metadata +81 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bd21afb5b92c9e7c0e712459ca3f3af0ce3fe823
|
4
|
+
data.tar.gz: 1c5868fa247da36d91d14b176586620e6c7a1298
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3fe0b6acbf267039e172a49f8022e9d1a90ea8f33b7e472f7fb442b645a9bfe8105bc5151943fc7fb309fd6abcbf0ce6c9d066658190a7d590cdb5e2f49bdead
|
7
|
+
data.tar.gz: 07cc6ca0d115cf69cd8e189756583dbe2325a74ac90bfc7cc27c9326df41c1f079f73a267e4f2b7d637a9e870000a5d7a683a72f54efccaf8e3231193de015e5
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
TODO
|
data/README.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
rafka-rb: Ruby driver for Rafka
|
2
|
+
===============================================================================
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/rafka.svg)](https://badge.fury.io/rb/rafka-rb)
|
4
|
+
[![Documentation](http://img.shields.io/badge/yard-docs-blue.svg)](http://www.rubydoc.info/github/skroutz/rafka-rb)
|
5
|
+
|
6
|
+
Rafka is a thin Ruby client library for [Rafka](https://github.com/skroutz/rafka-rb),
|
7
|
+
providing a consumer and a producer with simple semantics. It is backed by
|
8
|
+
[redis-rb](https://github.com/redis/redis-rb).
|
9
|
+
|
10
|
+
View the [API documentation](http://www.rubydoc.info/github/skroutz/rafka-rb).
|
11
|
+
|
12
|
+
Status
|
13
|
+
-------------------------------------------------------------------------------
|
14
|
+
|
15
|
+
Rafka is not yet stable and therefore is _not_ recommended for production use.
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
Getting started
|
26
|
+
-------------------------------------------------------------------------------
|
27
|
+
Install rafka-rb:
|
28
|
+
|
29
|
+
```shell
|
30
|
+
$ gem install rafka
|
31
|
+
```
|
32
|
+
|
33
|
+
If you're using Bundler, add it to your Gemfile:
|
34
|
+
```ruby
|
35
|
+
gem "rafka"
|
36
|
+
```
|
37
|
+
and run `bundle install`.
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
Usage
|
46
|
+
-------------------------------------------------------------------------------
|
47
|
+
|
48
|
+
### Producer
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
require "rafka"
|
52
|
+
|
53
|
+
prod = Rafka::Producer.new(host: "localhost", port: 6380)
|
54
|
+
prod.produce("greetings", "Hello there!") # produce to topic "greetings"
|
55
|
+
```
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
### Consumer
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
require "rafka"
|
64
|
+
|
65
|
+
cons = Rafka::Consumer.new(topic: "greetings", group: "myapp", id: "greeter1")
|
66
|
+
cons.consume # => "Hello there!"
|
67
|
+
|
68
|
+
# with a block
|
69
|
+
cons.consume { |msg| puts "Received: #{msg.value}" } # => "Hello there!"
|
70
|
+
```
|
71
|
+
|
72
|
+
`Rafka::Consumer#consume` automatically commits the offsets when the given block
|
73
|
+
is executed without raising any exceptions.
|
data/lib/rafka.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "redis"
|
2
|
+
|
3
|
+
require "rafka/errors"
|
4
|
+
require "rafka/generic_commands"
|
5
|
+
require "rafka/message"
|
6
|
+
require "rafka/version"
|
7
|
+
|
8
|
+
require "rafka/consumer"
|
9
|
+
require "rafka/producer"
|
10
|
+
|
11
|
+
module Rafka
|
12
|
+
DEFAULTS = {
|
13
|
+
host: "localhost",
|
14
|
+
port: 6380,
|
15
|
+
reconnect_attempts: 0,
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module Rafka
|
4
|
+
class Consumer
|
5
|
+
include GenericCommands
|
6
|
+
|
7
|
+
REQUIRED = [:group, :topic]
|
8
|
+
|
9
|
+
# The underlying Redis client object
|
10
|
+
attr_reader :redis
|
11
|
+
|
12
|
+
# Create a new client instance.
|
13
|
+
#
|
14
|
+
# @param [Hash] opts
|
15
|
+
# @option opts [String] :host ("localhost") server hostname
|
16
|
+
# @option opts [Fixnum] :port (6380) server port
|
17
|
+
# @option opts [String] :topic Kafka topic to consume (required)
|
18
|
+
# @option opts [String] :group Kafka consumer group name (required)
|
19
|
+
# @option opts [String] :id (random) Kafka consumer id
|
20
|
+
# @option opts [Hash] :redis_opts ({}) Optional configuration for the
|
21
|
+
# underlying Redis client
|
22
|
+
def initialize(opts={})
|
23
|
+
opts[:redis_opts] = {} if !opts[:redis_opts]
|
24
|
+
opts = parse_opts(opts)
|
25
|
+
client_id = "#{opts[:group]}:#{opts[:id]}"
|
26
|
+
@redis = Redis.new(host: opts[:host], port: opts[:port], id: client_id)
|
27
|
+
@topic = "topics:#{opts[:topic]}"
|
28
|
+
end
|
29
|
+
|
30
|
+
# Fetch the next message.
|
31
|
+
#
|
32
|
+
# @param timeout [Fixnum] the time in seconds to wait for a message
|
33
|
+
#
|
34
|
+
# @raise [MalformedMessage] if the message from Rafka cannot be parsed
|
35
|
+
#
|
36
|
+
# @return [nil, Message] the message, if any
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
# consume(5) { |msg| puts "I received #{msg.value}" }
|
40
|
+
def consume(timeout=5)
|
41
|
+
msg = @redis.blpop(@topic, timeout: timeout)
|
42
|
+
|
43
|
+
return if !msg
|
44
|
+
|
45
|
+
msg = Message.new(msg)
|
46
|
+
|
47
|
+
begin
|
48
|
+
raised = false
|
49
|
+
yield(msg) if block_given?
|
50
|
+
rescue => e
|
51
|
+
raised = true
|
52
|
+
raise e
|
53
|
+
end
|
54
|
+
|
55
|
+
msg
|
56
|
+
ensure
|
57
|
+
if msg && !raised
|
58
|
+
@redis.rpush("acks", "#{msg.topic}:#{msg.partition}:#{msg.offset}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def parse_opts(opts)
|
65
|
+
options = DEFAULTS.dup.merge(opts).merge(opts[:redis_opts])
|
66
|
+
options[:id] = SecureRandom.hex if !options[:id]
|
67
|
+
|
68
|
+
REQUIRED.each do |opt|
|
69
|
+
raise "#{opt.inspect} option not provided" if !options[opt]
|
70
|
+
end
|
71
|
+
|
72
|
+
options
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/rafka/errors.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Rafka
|
2
|
+
# Commands available on both {Producer} and {Consumer}.
|
3
|
+
module GenericCommands
|
4
|
+
# @see https://redis.io/commands/ping
|
5
|
+
def ping
|
6
|
+
@redis.ping
|
7
|
+
end
|
8
|
+
|
9
|
+
# @see https://redis.io/commands/quit
|
10
|
+
def quit
|
11
|
+
@redis.quit
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Rafka
|
2
|
+
# Message represents a message consumed from a topic.
|
3
|
+
class Message
|
4
|
+
attr :topic, :partition, :offset, :value
|
5
|
+
|
6
|
+
def initialize(msg)
|
7
|
+
if !msg.is_a?(Array) || msg.size != 8
|
8
|
+
raise MalformedMessage.new(msg)
|
9
|
+
end
|
10
|
+
|
11
|
+
@topic = msg[1]
|
12
|
+
@partition = msg[3]
|
13
|
+
@offset = msg[5]
|
14
|
+
@value = msg[7]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Rafka
|
2
|
+
class Producer
|
3
|
+
# Access the underlying Redis client object
|
4
|
+
attr_reader :redis
|
5
|
+
|
6
|
+
# Create a new client instance.
|
7
|
+
#
|
8
|
+
# @param [Hash] opts
|
9
|
+
# @option opts [String] :host ("localhost") server hostname
|
10
|
+
# @option opts [Fixnum] :port (6380) server port
|
11
|
+
# @options opts [Hash] :redis_opts Configuration options for the underlying
|
12
|
+
# Redis client
|
13
|
+
#
|
14
|
+
# @return [Producer]
|
15
|
+
def initialize(opts = {})
|
16
|
+
opts[:redis_opts] = {} if !opts[:redis_opts]
|
17
|
+
opts = parse_opts(opts)
|
18
|
+
@redis = Redis.new(host: opts[:host], port: opts[:port])
|
19
|
+
end
|
20
|
+
|
21
|
+
# Produce a message. This is a non-blocking operation.
|
22
|
+
#
|
23
|
+
# @param topic [String]
|
24
|
+
# @param message [#to_s]
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# produce("greetings", "Hello there!")
|
28
|
+
def produce(topic, message)
|
29
|
+
@redis.rpushx("topics:#{topic}", message.to_s)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Flush any buffered messages. Blocks until all messages are flushed or
|
33
|
+
# timeout exceeds.
|
34
|
+
#
|
35
|
+
# @param timeout_ms [Fixnum] (5000) The timeout in milliseconds
|
36
|
+
#
|
37
|
+
# @return [Fixnum] The number of unflushed messages
|
38
|
+
def flush(timeout_ms=5000)
|
39
|
+
@redis.dump(timeout_ms.to_s)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def parse_opts(opts)
|
45
|
+
options = DEFAULTS.dup.merge(opts).merge(opts[:redis_opts])
|
46
|
+
options
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rafka
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Agis Anastasopoulos
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-06-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: redis
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry-byebug
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: A Ruby client library for Rafka, with consumer and producer implementations.
|
42
|
+
email:
|
43
|
+
- agis.anast@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- CHANGELOG.md
|
49
|
+
- README.md
|
50
|
+
- lib/rafka.rb
|
51
|
+
- lib/rafka/consumer.rb
|
52
|
+
- lib/rafka/errors.rb
|
53
|
+
- lib/rafka/generic_commands.rb
|
54
|
+
- lib/rafka/message.rb
|
55
|
+
- lib/rafka/producer.rb
|
56
|
+
- lib/rafka/version.rb
|
57
|
+
homepage: https://github.com/skroutz/rafka-rb
|
58
|
+
licenses:
|
59
|
+
- MIT
|
60
|
+
metadata: {}
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 2.5.2
|
78
|
+
signing_key:
|
79
|
+
specification_version: 4
|
80
|
+
summary: Ruby driver for Rafka
|
81
|
+
test_files: []
|