pulsar_sdk 0.8.8

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 (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