pulsar_sdk 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +51 -0
  3. data/Gemfile +6 -0
  4. data/LICENSE +201 -0
  5. data/README.md +107 -0
  6. data/Rakefile +2 -0
  7. data/bin/console +15 -0
  8. data/bin/setup +8 -0
  9. data/lib/protobuf/pulsar_api.pb.rb +710 -0
  10. data/lib/protobuf/pulsar_api.proto +934 -0
  11. data/lib/protobuf/validate.rb +41 -0
  12. data/lib/pulsar_admin.rb +14 -0
  13. data/lib/pulsar_admin/api.rb +215 -0
  14. data/lib/pulsar_sdk.rb +55 -0
  15. data/lib/pulsar_sdk/client.rb +13 -0
  16. data/lib/pulsar_sdk/client/connection.rb +371 -0
  17. data/lib/pulsar_sdk/client/connection_pool.rb +79 -0
  18. data/lib/pulsar_sdk/client/rpc.rb +67 -0
  19. data/lib/pulsar_sdk/consumer.rb +13 -0
  20. data/lib/pulsar_sdk/consumer/base.rb +148 -0
  21. data/lib/pulsar_sdk/consumer/manager.rb +127 -0
  22. data/lib/pulsar_sdk/consumer/message_tracker.rb +86 -0
  23. data/lib/pulsar_sdk/options.rb +6 -0
  24. data/lib/pulsar_sdk/options/base.rb +10 -0
  25. data/lib/pulsar_sdk/options/connection.rb +51 -0
  26. data/lib/pulsar_sdk/options/consumer.rb +34 -0
  27. data/lib/pulsar_sdk/options/producer.rb +14 -0
  28. data/lib/pulsar_sdk/options/reader.rb +7 -0
  29. data/lib/pulsar_sdk/options/tls.rb +8 -0
  30. data/lib/pulsar_sdk/producer.rb +14 -0
  31. data/lib/pulsar_sdk/producer/base.rb +154 -0
  32. data/lib/pulsar_sdk/producer/manager.rb +67 -0
  33. data/lib/pulsar_sdk/producer/message.rb +47 -0
  34. data/lib/pulsar_sdk/producer/router.rb +100 -0
  35. data/lib/pulsar_sdk/protocol.rb +8 -0
  36. data/lib/pulsar_sdk/protocol/frame.rb +53 -0
  37. data/lib/pulsar_sdk/protocol/lookup.rb +55 -0
  38. data/lib/pulsar_sdk/protocol/message.rb +55 -0
  39. data/lib/pulsar_sdk/protocol/namespace.rb +22 -0
  40. data/lib/pulsar_sdk/protocol/partitioned.rb +54 -0
  41. data/lib/pulsar_sdk/protocol/reader.rb +67 -0
  42. data/lib/pulsar_sdk/protocol/structure.rb +93 -0
  43. data/lib/pulsar_sdk/protocol/topic.rb +74 -0
  44. data/lib/pulsar_sdk/tweaks.rb +10 -0
  45. data/lib/pulsar_sdk/tweaks/assign_attributes.rb +30 -0
  46. data/lib/pulsar_sdk/tweaks/base_command.rb +66 -0
  47. data/lib/pulsar_sdk/tweaks/binary_heap.rb +133 -0
  48. data/lib/pulsar_sdk/tweaks/clean_inspect.rb +15 -0
  49. data/lib/pulsar_sdk/tweaks/time_at_microsecond.rb +27 -0
  50. data/lib/pulsar_sdk/tweaks/timeout_queue.rb +52 -0
  51. data/lib/pulsar_sdk/tweaks/wait_map.rb +81 -0
  52. data/lib/pulsar_sdk/version.rb +3 -0
  53. data/pulsar_sdk.gemspec +31 -0
  54. metadata +151 -0
@@ -0,0 +1,10 @@
1
+ require 'pulsar_sdk/tweaks/assign_attributes'
2
+ require 'pulsar_sdk/tweaks/clean_inspect'
3
+ require 'pulsar_sdk/tweaks/base_command'
4
+ require 'pulsar_sdk/tweaks/time_at_microsecond'
5
+ require 'pulsar_sdk/tweaks/timeout_queue'
6
+ require 'pulsar_sdk/tweaks/wait_map'
7
+ require 'pulsar_sdk/tweaks/binary_heap'
8
+
9
+ # 扩展type的判断方法,方便书写,统一以 typeof_ 开头
10
+ Pulsar::Proto::BaseCommand.prepend PulsarSdk::Tweaks::BaseCommand
@@ -0,0 +1,30 @@
1
+ module PulsarSdk
2
+ module Tweaks
3
+ module AssignAttributes
4
+ def initialize(opts = {})
5
+ set_default
6
+
7
+ assign_attributes(opts)
8
+
9
+ remove_empty_instance_variables!
10
+ end
11
+
12
+ def assign_attributes(opts)
13
+ opts.each do |k, v|
14
+ method = "#{k}="
15
+ next unless self.respond_to?(method)
16
+ self.public_send method, v
17
+ end
18
+ end
19
+
20
+ private
21
+ def set_default; end
22
+
23
+ def remove_empty_instance_variables!
24
+ instance_variables.each do |x|
25
+ remove_instance_variable(x) if instance_variable_get(x).nil?
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,66 @@
1
+ module PulsarSdk
2
+ module Tweaks
3
+ module BaseCommand
4
+ attr_accessor :seq_generator
5
+
6
+ # add some helper
7
+ # def set_request_id
8
+ # def set_consumer_id
9
+ # def set_producer_id
10
+ # def set_sequence_id
11
+ # def get_request_id
12
+ # def get_consumer_id
13
+ # def get_producer_id
14
+ # def get_sequence_id
15
+ # NOTE before use setter must set `seq_generator`
16
+ [:request_id, :consumer_id, :producer_id, :sequence_id].each do |x|
17
+ define_method "set_#{x}" do
18
+ if self.seq_generator.nil?
19
+ PulsarSdk.logger.warn(__method__){"seq_generator was not set!! action has no effect"}
20
+ return
21
+ end
22
+
23
+ method_ = "#{x}="
24
+ current_id = nil
25
+ attribute_names.each do |name|
26
+ next unless self[name].respond_to?(method_)
27
+
28
+ # NOTE keep same id name with same value, like sequence_id
29
+ current_id ||= self.seq_generator.public_send("new_#{x}")
30
+
31
+ self[name].public_send(method_, current_id)
32
+ end
33
+
34
+ current_id
35
+ end
36
+
37
+ define_method "get_#{x}" do
38
+ attribute_names.each do |name|
39
+ next unless self[name].respond_to?(x)
40
+ return self[name][x.to_s]
41
+ end
42
+ nil
43
+ end
44
+ end
45
+
46
+ Pulsar::Proto::BaseCommand::Type.constants.each do |x|
47
+ method = "typeof_#{x.to_s.downcase}?"
48
+ define_method method do
49
+ self.type == x
50
+ end
51
+ end
52
+
53
+ def handle_ids
54
+ set_request_id
55
+ set_consumer_id
56
+ set_producer_id
57
+ set_sequence_id
58
+ end
59
+
60
+ private
61
+ def attribute_names
62
+ self.class.descriptor.map(&:name)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,133 @@
1
+ module PulsarSdk
2
+ module Tweaks
3
+ class BinaryHeap
4
+ attr_reader :data
5
+
6
+ # default is max heap, custom compare lambda to build your sort
7
+ def initialize(ary=nil, &block)
8
+ @cmp = block || lambda{|parent, child| parent <=> child }
9
+ @mutex = Mutex.new
10
+
11
+ raise "type of ary must be Array or its subclass" unless ary.nil? || ary.is_a?(Array)
12
+ @data = build_from(ary)
13
+ end
14
+
15
+ # insert an element list into heap, it will automatic adjust
16
+ def insert(*elements)
17
+ @mutex.synchronize do
18
+ elements.each do |x|
19
+ data.push(x)
20
+ adjust(:bottom_up)
21
+ end
22
+ end
23
+ end
24
+
25
+ # take the heap element and adjust heap
26
+ def shift
27
+ @mutex.synchronize do
28
+ return if data.empty?
29
+ e = data.first
30
+ data[0] = data.last
31
+ data.pop
32
+ adjust(:top_down)
33
+ e
34
+ end
35
+ end
36
+
37
+ # return the the top element of the heap
38
+ def top
39
+ data.first
40
+ end
41
+
42
+ private
43
+ def build_from(ary)
44
+ return [] if ary.nil? || ary.empty?
45
+
46
+ heap = BinaryHeap.new(&(@cmp))
47
+ heap.insert(*ary)
48
+ heap.data
49
+ end
50
+
51
+ def swap(i, j)
52
+ data[i], data[j] = data[j], data[i]
53
+ end
54
+
55
+ def compare(i, j)
56
+ @cmp.call(data[i], data[j]) >= 0
57
+ end
58
+
59
+ def p_idx(child_idx)
60
+ return nil if child_idx == 0
61
+ child_idx%2 == 0 ? (child_idx-2)/2 : child_idx/2
62
+ end
63
+
64
+ def l_idx(parent_idx)
65
+ (parent_idx << 1) + 1
66
+ end
67
+
68
+ def r_idx(parent_idx)
69
+ (parent_idx << 1) + 2
70
+ end
71
+
72
+ def lchid(parent_idx)
73
+ data[l_idx(parent_idx)]
74
+ end
75
+
76
+ def rchild(parent_idx)
77
+ data[r_idx(parent_idx)]
78
+ end
79
+
80
+ def good?(idx)
81
+ if !lchid(idx).nil?
82
+ return false unless compare(idx, l_idx(idx))
83
+ end
84
+
85
+ if !rchild(idx).nil?
86
+ return false unless compare(idx, r_idx(idx))
87
+ end
88
+
89
+ true
90
+ end
91
+
92
+ # make the heap in good shape
93
+ def adjust(direction = :top_down)
94
+ return if data.size < 2
95
+
96
+ case direction
97
+ when :top_down
98
+ parent_idx = 0
99
+ until good?(parent_idx)
100
+ child_idx = find_child_idx(parent_idx)
101
+ swap(parent_idx, child_idx)
102
+ parent_idx = child_idx
103
+ end
104
+ when :bottom_up
105
+ child_idx = data.size - 1
106
+ parent_idx = p_idx(child_idx)
107
+ until child_idx == 0 || compare(parent_idx, child_idx)
108
+ swap(parent_idx, child_idx)
109
+ child_idx = parent_idx
110
+ parent_idx = p_idx(child_idx)
111
+ end
112
+ else
113
+ raise "invalid direction type"
114
+ end
115
+ end
116
+
117
+ def find_child_idx(parent_idx)
118
+ l = lchid(parent_idx)
119
+ r = rchild(parent_idx)
120
+
121
+ return if l.nil? && r.nil?
122
+
123
+ l_idx_ = l_idx(parent_idx)
124
+ r_idx_ = r_idx(parent_idx)
125
+
126
+ return r_idx_ if l.nil?
127
+ return l_idx_ if r.nil?
128
+
129
+ compare(l_idx_, r_idx_) ? l_idx_ : r_idx_
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,15 @@
1
+ module PulsarSdk
2
+ module Tweaks
3
+ module CleanInspect
4
+ def inspect
5
+ s = instance_variables.map do |x|
6
+ v = instance_variable_get(x)
7
+ next if v.is_a?(Proc)
8
+ "#{x}: #{v}"
9
+ end.join(', ')
10
+
11
+ "<#{self.class.name} #{s}>"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ module PulsarSdk
2
+ module Tweaks
3
+ module TimeAtMicrosecond
4
+ def self.prepended(base)
5
+ class << base
6
+ prepend ClassMethods
7
+ end
8
+ end
9
+
10
+ def timestamp
11
+ (self.to_f * 1000).floor
12
+ end
13
+
14
+ module ClassMethods
15
+ def at_timestamp(v)
16
+ second, micro = v.divmod(1000)
17
+ self.at(second, micro * 1000)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ # 扩展默认时间方法,增加毫秒时间戳相关处理
25
+ class TimeX < Time
26
+ prepend PulsarSdk::Tweaks::TimeAtMicrosecond
27
+ end
@@ -0,0 +1,52 @@
1
+ module PulsarSdk
2
+ module Tweaks
3
+ class TimeoutQueue
4
+ def initialize
5
+ @mutex = Mutex.new
6
+ @queue = []
7
+ @received = ConditionVariable.new
8
+ @closed = false
9
+ end
10
+
11
+ def add(*args)
12
+ @mutex.synchronize do
13
+ @queue << args
14
+ @received.signal
15
+ end
16
+ end
17
+
18
+ def clear
19
+ @mutex.synchronize do
20
+ @queue.clear
21
+ end
22
+ end
23
+
24
+ def size
25
+ @queue.size
26
+ end
27
+
28
+ # timeout 数字,单位秒
29
+ def pop(timeout = nil)
30
+ @mutex.synchronize do
31
+ if timeout.nil?
32
+ while !@closed && @queue.empty?
33
+ @received.wait(@mutex)
34
+ end
35
+ elsif @queue.empty? && timeout != 0
36
+ timeout_at = TimeX.now.to_f + timeout
37
+ while !@closed && @queue.empty? && (res = timeout_at - TimeX.now.to_f) > 0
38
+ @received.wait(@mutex, res)
39
+ end
40
+ end
41
+
42
+ @queue.pop
43
+ end
44
+ end
45
+
46
+ def close
47
+ @closed = true
48
+ @received.broadcast
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,81 @@
1
+ module PulsarSdk
2
+ module Tweaks
3
+ class WaitMap
4
+ def initialize
5
+ @mutex = Mutex.new
6
+ @map = {}
7
+
8
+ @wait = {}
9
+ @closed = false
10
+ end
11
+
12
+ def add(id, value)
13
+ @mutex.synchronize do
14
+ @map[id] = value
15
+ _, signal = @wait[id]
16
+ signal.signal unless signal.nil?
17
+ end
18
+ value
19
+ end
20
+
21
+ def clear
22
+ @mutex.synchronize do
23
+ @map.each {|k, v| yield k, v} if block_given?
24
+
25
+ @map = {}
26
+ end
27
+ true
28
+ end
29
+
30
+ def each(&block)
31
+ @mutex.synchronize do
32
+ @map.each {|k, v| yield k, v}
33
+ end
34
+ end
35
+
36
+ # 不会删除元素
37
+ def find(id)
38
+ @mutex.synchronize do
39
+ @map[id]
40
+ end
41
+ end
42
+
43
+ def delete(id, timeout = nil)
44
+ mutex, signal = []
45
+
46
+ @mutex.synchronize do
47
+ return @map.delete(id) if @map.has_key?(id)
48
+
49
+ @wait[id] ||= [Mutex.new, ConditionVariable.new]
50
+ mutex, signal = @wait[id]
51
+ end
52
+
53
+ mutex.synchronize do
54
+ if timeout.nil?
55
+ while !@closed && !@map.has_key?(id)
56
+ signal.wait(mutex)
57
+ end
58
+ elsif @map.empty? && timeout != 0
59
+ timeout_at = TimeX.now.to_f + timeout
60
+ while !@closed && !@map.has_key?(id) && (res = timeout_at - TimeX.now.to_f) > 0
61
+ signal.wait(mutex, res)
62
+ end
63
+ end
64
+ end
65
+
66
+ @mutex.synchronize do
67
+ @wait.delete id
68
+ @map.delete id
69
+ end
70
+ end
71
+
72
+ def close
73
+ @closed = true
74
+ @wait.each do |_, v|
75
+ _, signal = v
76
+ signal.broadcast
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,3 @@
1
+ module PulsarSdk
2
+ VERSION = "0.8.8"
3
+ end
@@ -0,0 +1,31 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "pulsar_sdk/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "pulsar_sdk"
8
+ spec.version = PulsarSdk::VERSION
9
+ spec.authors = 'archfish'
10
+ spec.email = ["weihailang@gmail.com"]
11
+ spec.license = 'Apache License 2.0'
12
+
13
+ spec.summary = %q{A pure ruby client for Apache Pulsar}
14
+ spec.description = %q{A pure ruby client for Apache Pulsar}
15
+ spec.homepage = "https://github.com/archfish/pulsar_sdk"
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|examples)/}) }
21
+ end
22
+
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_dependency 'google-protobuf', '~> 3.11'
27
+ spec.add_dependency 'digest-crc', '~> 0.4'
28
+
29
+ spec.add_development_dependency "bundler", "> 1.17"
30
+ spec.add_development_dependency "rake", "> 10"
31
+ end