pubcontrol 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ab97545468d3337e4e281e5d36f515a3acb707d4
4
- data.tar.gz: f9649e54bce224b03683182c09583c283b358e4c
3
+ metadata.gz: 72a4849cda3e8c5921a09ff97df674726be6bc06
4
+ data.tar.gz: 53cb42aa569100d5f2d788545bcdd8a43435e904
5
5
  SHA512:
6
- metadata.gz: ffe3037a12a43e76a5a1fbc09cccda35833c3c5528c04ee66d3ccdb670ae657f0d300a4e88a1410d63e8d83959083a8a9836dfe7cfc68f3cf695fe85093751bc
7
- data.tar.gz: cfd4eb7cd7c050d8e67c5741545a1ceba708f0f4e29b32d5c2f7a423ebbe7b26508cfffc408e850d121afc6be63ed32fc05dc5e4d16604038b96f65297c3cf8b
6
+ metadata.gz: 8c6bec7d9dd4efd0806012f471449ef6086a5c97427fb13ce8ca26290a679d0809e94e953ec1f294dfc4a01f3f7c10c42c517ab409ef90e19705767fe2911a56
7
+ data.tar.gz: beda44c933432151d9ccc7b7fa73430c789830ca5f1e9db0f76a4a7fb5d9ec56def1c61913d551799c429af14c2b7884a96cafb8edf5de1f081088e30418e6b6
@@ -1,11 +1,11 @@
1
- # format.rb
1
+ # pcccbhandler.rb
2
2
  # ~~~~~~~~~
3
- # This module implements the PubControlCallbackHandler class.
3
+ # This module implements the PubControlClientCallbackHandler class.
4
4
  # :authors: Konstantin Bokarius.
5
5
  # :copyright: (c) 2015 by Fanout, Inc.
6
6
  # :license: MIT, see LICENSE for more details.
7
7
 
8
- class PubControlCallbackHandler
8
+ class PubControlClientCallbackHandler
9
9
  def initialize(num_calls, callback)
10
10
  @num_calls = num_calls
11
11
  @callback = callback
data/lib/pubcontrol.rb CHANGED
@@ -5,187 +5,60 @@
5
5
  # :copyright: (c) 2015 by Fanout, Inc.
6
6
  # :license: MIT, see LICENSE for more details.
7
7
 
8
- require 'algorithms'
9
- require 'thread'
10
- require 'base64'
11
- require 'jwt'
12
- require 'json'
13
- require 'net/http'
14
- require_relative 'item.rb'
15
8
  require_relative 'format.rb'
16
- require_relative 'pubcontrolset.rb'
9
+ require_relative 'item.rb'
10
+ require_relative 'pubcontrolclient.rb'
11
+ require_relative 'pcccbhandler.rb'
17
12
 
18
13
  class PubControl
19
- attr_accessor :req_queue
20
-
21
- def initialize(uri)
22
- @uri = uri
23
- @lock = Mutex.new
24
- @thread = nil
25
- @thread_cond = nil
26
- @thread_mutex = nil
27
- @req_queue = Containers::Deque.new
28
- @auth_basic_user = nil
29
- @auth_basic_pass = nil
30
- @auth_jwt_claim = nil
31
- @auth_jwt_key = nil
32
- end
33
-
34
- def set_auth_basic(username, password)
35
- @lock.synchronize do
36
- @auth_basic_user = username
37
- @auth_basic_pass = password
14
+ def initialize(config=nil)
15
+ @clients = Array.new
16
+ if !config.nil?
17
+ apply_config(config)
38
18
  end
39
19
  end
40
20
 
41
- def set_auth_jwt(claim, key)
42
- @lock.synchronize do
43
- @auth_jwt_claim = claim
44
- @auth_jwt_key = key
45
- end
21
+ def remove_all_clients
22
+ @clients = Array.new
46
23
  end
47
24
 
48
- def publish(channel, item)
49
- export = item.export
50
- export['channel'] = channel
51
- uri = nil
52
- auth = nil
53
- @lock.synchronize do
54
- uri = @uri
55
- auth = gen_auth_header
56
- end
57
- PubControl.pubcall(uri, auth, [export])
25
+ def add_client(client)
26
+ @clients.push(client)
58
27
  end
59
28
 
60
- def publish_async(channel, item, callback=nil)
61
- export = item.export
62
- export['channel'] = channel
63
- uri = nil
64
- auth = nil
65
- @lock.synchronize do
66
- uri = @uri
67
- auth = gen_auth_header
68
- ensure_thread
29
+ def apply_config(config)
30
+ if !config.is_a?(Array)
31
+ config = [config]
69
32
  end
70
- queue_req(['pub', uri, auth, export, callback])
71
- end
72
-
73
- def finish
74
- @lock.synchronize do
75
- if !@thread.nil?
76
- queue_req(['stop'])
77
- @thread.join
78
- @thread = nil
79
- end
80
- end
81
- end
82
-
83
- def pubworker
84
- quit = false
85
- while !quit do
86
- @thread_mutex.lock
87
- if @req_queue.length == 0
88
- @thread_cond.wait(@thread_mutex)
89
- if @req_queue.length == 0
90
- @thread_mutex.unlock
91
- next
92
- end
93
- end
94
- reqs = Array.new
95
- while @req_queue.length > 0 and reqs.length < 10 do
96
- m = @req_queue.pop_front
97
- if m[0] == 'stop'
98
- quit = true
99
- break
100
- end
101
- reqs.push([m[1], m[2], m[3], m[4]])
102
- end
103
- @thread_mutex.unlock
104
- if reqs.length > 0
105
- PubControl.pubbatch(reqs)
33
+ config.each do |entry|
34
+ pub = PubControlClient.new(entry['uri'])
35
+ if entry.key?('iss')
36
+ pub.set_auth_jwt({'iss' => entry['iss']}, entry['key'])
106
37
  end
38
+ @clients.push(pub)
107
39
  end
108
40
  end
109
41
 
110
- def self.pubcall(uri, auth_header, items)
111
- uri = URI(uri + '/publish/')
112
- content = Hash.new
113
- content['items'] = items
114
- request = Net::HTTP::Post.new(uri.request_uri)
115
- request.body = content.to_json
116
- if !auth_header.nil?
117
- request['Authorization'] = auth_header
118
- end
119
- request['Content-Type'] = 'application/json'
120
- use_ssl = uri.scheme == 'https'
121
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: use_ssl) do |http|
122
- http.request(request)
123
- end
124
- # REVIEW: HTTPSuccess does not include 3xx status codes.
125
- if !response.kind_of? Net::HTTPSuccess
126
- raise 'failed to publish: ' + response.class.to_s + ' ' +
127
- response.message
42
+ def finish
43
+ @clients.each do |pub|
44
+ pub.finish
128
45
  end
129
46
  end
130
47
 
131
- def self.pubbatch(reqs)
132
- raise 'reqs length == 0' unless reqs.length > 0
133
- uri = reqs[0][0]
134
- auth_header = reqs[0][1]
135
- items = Array.new
136
- callbacks = Array.new
137
- reqs.each do |req|
138
- items.push(req[2])
139
- callbacks.push(req[3])
140
- end
141
- begin
142
- PubControl.pubcall(uri, auth_header, items)
143
- result = [true, '']
144
- rescue => e
145
- result = [false, e.message]
146
- end
147
- callbacks.each do |callback|
148
- if !callback.nil?
149
- callback.call(result[0], result[1])
150
- end
48
+ def publish(channel, item)
49
+ @clients.each do |pub|
50
+ pub.publish(channel, item)
151
51
  end
152
52
  end
153
53
 
154
- def self.timestamp_utcnow
155
- return Time.now.utc.to_i
156
- end
157
-
158
- private
159
-
160
- def gen_auth_header
161
- if !@auth_basic_user.nil?
162
- return 'Basic ' + Base64.encode64(
163
- '#{@auth_basic_user}:#{@auth_basic_pass}')
164
- elsif !@auth_jwt_claim.nil?
165
- if !@auth_jwt_claim.has_key?('exp')
166
- claim = @auth_jwt_claim.clone
167
- claim['exp'] = PubControl.timestamp_utcnow + 3600
168
- else
169
- claim = @auth_jwt_claim
170
- end
171
- return 'Bearer ' + JWT.encode(claim, @auth_jwt_key)
172
- else
173
- return nil
54
+ def publish_async(channel, item, callback=nil)
55
+ cb = nil
56
+ if !callback.nil?
57
+ cb = PubControlClientCallbackHandler.new(@clients.length, callback).
58
+ handler_method_symbol
174
59
  end
175
- end
176
-
177
- def ensure_thread
178
- if @thread.nil?
179
- @thread_cond = ConditionVariable.new
180
- @thread_mutex = Mutex.new
181
- @thread = Thread.new { pubworker }
60
+ @clients.each do |pub|
61
+ pub.publish_async(channel, item, cb)
182
62
  end
183
63
  end
184
-
185
- def queue_req(req)
186
- @thread_mutex.lock
187
- @req_queue.push_back(req)
188
- @thread_cond.signal
189
- @thread_mutex.unlock
190
- end
191
64
  end
@@ -0,0 +1,188 @@
1
+ # pubcontrolclient.rb
2
+ # ~~~~~~~~~
3
+ # This module implements the PubControlClient class.
4
+ # :authors: Konstantin Bokarius.
5
+ # :copyright: (c) 2015 by Fanout, Inc.
6
+ # :license: MIT, see LICENSE for more details.
7
+
8
+ require 'algorithms'
9
+ require 'thread'
10
+ require 'base64'
11
+ require 'jwt'
12
+ require 'json'
13
+ require 'net/http'
14
+ require_relative 'item.rb'
15
+
16
+ class PubControlClient
17
+ attr_accessor :req_queue
18
+
19
+ def initialize(uri)
20
+ @uri = uri
21
+ @lock = Mutex.new
22
+ @thread = nil
23
+ @thread_cond = nil
24
+ @thread_mutex = nil
25
+ @req_queue = Containers::Deque.new
26
+ @auth_basic_user = nil
27
+ @auth_basic_pass = nil
28
+ @auth_jwt_claim = nil
29
+ @auth_jwt_key = nil
30
+ end
31
+
32
+ def set_auth_basic(username, password)
33
+ @lock.synchronize do
34
+ @auth_basic_user = username
35
+ @auth_basic_pass = password
36
+ end
37
+ end
38
+
39
+ def set_auth_jwt(claim, key)
40
+ @lock.synchronize do
41
+ @auth_jwt_claim = claim
42
+ @auth_jwt_key = key
43
+ end
44
+ end
45
+
46
+ def publish(channel, item)
47
+ export = item.export
48
+ export['channel'] = channel
49
+ uri = nil
50
+ auth = nil
51
+ @lock.synchronize do
52
+ uri = @uri
53
+ auth = gen_auth_header
54
+ end
55
+ PubControlClient.pubcall(uri, auth, [export])
56
+ end
57
+
58
+ def publish_async(channel, item, callback=nil)
59
+ export = item.export
60
+ export['channel'] = channel
61
+ uri = nil
62
+ auth = nil
63
+ @lock.synchronize do
64
+ uri = @uri
65
+ auth = gen_auth_header
66
+ ensure_thread
67
+ end
68
+ queue_req(['pub', uri, auth, export, callback])
69
+ end
70
+
71
+ def finish
72
+ @lock.synchronize do
73
+ if !@thread.nil?
74
+ queue_req(['stop'])
75
+ @thread.join
76
+ @thread = nil
77
+ end
78
+ end
79
+ end
80
+
81
+ def pubworker
82
+ quit = false
83
+ while !quit do
84
+ @thread_mutex.lock
85
+ if @req_queue.length == 0
86
+ @thread_cond.wait(@thread_mutex)
87
+ if @req_queue.length == 0
88
+ @thread_mutex.unlock
89
+ next
90
+ end
91
+ end
92
+ reqs = Array.new
93
+ while @req_queue.length > 0 and reqs.length < 10 do
94
+ m = @req_queue.pop_front
95
+ if m[0] == 'stop'
96
+ quit = true
97
+ break
98
+ end
99
+ reqs.push([m[1], m[2], m[3], m[4]])
100
+ end
101
+ @thread_mutex.unlock
102
+ if reqs.length > 0
103
+ PubControlClient.pubbatch(reqs)
104
+ end
105
+ end
106
+ end
107
+
108
+ def self.pubcall(uri, auth_header, items)
109
+ uri = URI(uri + '/publish/')
110
+ content = Hash.new
111
+ content['items'] = items
112
+ request = Net::HTTP::Post.new(uri.request_uri)
113
+ request.body = content.to_json
114
+ if !auth_header.nil?
115
+ request['Authorization'] = auth_header
116
+ end
117
+ request['Content-Type'] = 'application/json'
118
+ use_ssl = uri.scheme == 'https'
119
+ response = Net::HTTP.start(uri.host, uri.port, use_ssl: use_ssl) do |http|
120
+ http.request(request)
121
+ end
122
+ if !response.kind_of? Net::HTTPSuccess
123
+ raise 'failed to publish: ' + response.class.to_s + ' ' +
124
+ response.message
125
+ end
126
+ end
127
+
128
+ def self.pubbatch(reqs)
129
+ raise 'reqs length == 0' unless reqs.length > 0
130
+ uri = reqs[0][0]
131
+ auth_header = reqs[0][1]
132
+ items = Array.new
133
+ callbacks = Array.new
134
+ reqs.each do |req|
135
+ items.push(req[2])
136
+ callbacks.push(req[3])
137
+ end
138
+ begin
139
+ PubControlClient.pubcall(uri, auth_header, items)
140
+ result = [true, '']
141
+ rescue => e
142
+ result = [false, e.message]
143
+ end
144
+ callbacks.each do |callback|
145
+ if !callback.nil?
146
+ callback.call(result[0], result[1])
147
+ end
148
+ end
149
+ end
150
+
151
+ def self.timestamp_utcnow
152
+ return Time.now.utc.to_i
153
+ end
154
+
155
+ private
156
+
157
+ def gen_auth_header
158
+ if !@auth_basic_user.nil?
159
+ return 'Basic ' + Base64.encode64(
160
+ '#{@auth_basic_user}:#{@auth_basic_pass}')
161
+ elsif !@auth_jwt_claim.nil?
162
+ if !@auth_jwt_claim.has_key?('exp')
163
+ claim = @auth_jwt_claim.clone
164
+ claim['exp'] = PubControlClient.timestamp_utcnow + 3600
165
+ else
166
+ claim = @auth_jwt_claim
167
+ end
168
+ return 'Bearer ' + JWT.encode(claim, @auth_jwt_key)
169
+ else
170
+ return nil
171
+ end
172
+ end
173
+
174
+ def ensure_thread
175
+ if @thread.nil?
176
+ @thread_cond = ConditionVariable.new
177
+ @thread_mutex = Mutex.new
178
+ @thread = Thread.new { pubworker }
179
+ end
180
+ end
181
+
182
+ def queue_req(req)
183
+ @thread_mutex.lock
184
+ @req_queue.push_back(req)
185
+ @thread_cond.signal
186
+ @thread_mutex.unlock
187
+ end
188
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pubcontrol
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Bokarius
@@ -46,9 +46,9 @@ extra_rdoc_files: []
46
46
  files:
47
47
  - lib/format.rb
48
48
  - lib/item.rb
49
- - lib/pccbhandler.rb
49
+ - lib/pcccbhandler.rb
50
50
  - lib/pubcontrol.rb
51
- - lib/pubcontrolset.rb
51
+ - lib/pubcontrolclient.rb
52
52
  homepage: http://rubygems.org/gems/pubcontrol
53
53
  licenses:
54
54
  - MIT
data/lib/pubcontrolset.rb DELETED
@@ -1,72 +0,0 @@
1
- # pubcontrolset.rb
2
- # ~~~~~~~~~
3
- # This module implements the PubControlSet class.
4
- # :authors: Konstantin Bokarius.
5
- # :copyright: (c) 2015 by Fanout, Inc.
6
- # :license: MIT, see LICENSE for more details.
7
-
8
- require_relative 'pubcontrol.rb'
9
- require_relative 'pccbhandler.rb'
10
-
11
- class PubControlSet
12
- def initialize
13
- @pubs = Array.new
14
- at_exit { finish }
15
- end
16
-
17
- def clear
18
- @pubs = Array.new
19
- end
20
-
21
- def add(pub)
22
- @pubs.push(pub)
23
- end
24
-
25
- def apply_config(config)
26
- config.each do |entry|
27
- pub = PubControl.new(entry['uri'])
28
- if entry.key?('iss')
29
- pub.set_auth_jwt({'iss' => entry['iss']}, entry['key'])
30
- end
31
- @pubs.push(pub)
32
- end
33
- end
34
-
35
- def apply_grip_config(config)
36
- config.each do |entry|
37
- if !entry.key?('control_uri')
38
- next
39
- end
40
- pub = PubControl.new(entry['control_uri'])
41
- if !entry.key?('control_iss')
42
- pub.set_auth_jwt({'iss' => entry['control_iss']}, entry['key'])
43
- end
44
- @pubs.push(pub)
45
- end
46
- end
47
-
48
- def publish(channel, item)
49
- @pubs.each do |pub|
50
- pub.publish(channel, item)
51
- end
52
- end
53
-
54
- def publish_async(channel, item, callback=nil)
55
- cb = nil
56
- if !callback.nil?
57
- cb = PubControlCallbackHandler.new(@pubs.length, callback).
58
- handler_method_symbol
59
- end
60
- @pubs.each do |pub|
61
- pub.publish_async(channel, item, cb)
62
- end
63
- end
64
-
65
- private
66
-
67
- def finish
68
- @pubs.each do |pub|
69
- pub.finish
70
- end
71
- end
72
- end