pressure 0.1.5 → 0.1.6
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/pressure.rb +126 -23
- data/lib/pressure/version.rb +2 -1
- data/pressure.gemspec +10 -5
- metadata +69 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 875dd6186d88bf1269640e4166024fd481803a3d
|
4
|
+
data.tar.gz: d193fd7bc0074ba85eb6938fbbb68d08dca89eda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a3542194409705a6ad347b8ecaf06d4e15cb68e8cb11c9c2f7fcf9fd0e898ab5d09b26ab91f6152f8004088aa4344f8f99f74c30319d587760fd1565f8e1263
|
7
|
+
data.tar.gz: 142f22d60d5f869d8c8e939491cecb93f99fcb6523298be4edd902a0b84af9e37bfcf4f8eba7f1ffd0d52e4722690f8ccb46dd3273ccab69fc70c0fb93d721cd
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://travis-ci.org/bsdavidson/pressure)
|
4
4
|
|
5
|
-
|
5
|
+
Broadcast upstream data to downstream websocket clients.
|
6
6
|
|
7
7
|
Documentation is [available on RubyDoc.info](http://www.rubydoc.info/github/bsdavidson/pressure/).
|
8
8
|
|
data/lib/pressure.rb
CHANGED
@@ -1,38 +1,137 @@
|
|
1
|
-
|
1
|
+
require 'hamster'
|
2
|
+
require 'json'
|
2
3
|
require 'logger'
|
3
4
|
require 'time'
|
4
|
-
require 'json'
|
5
5
|
|
6
|
+
require_relative 'pressure/version'
|
7
|
+
|
8
|
+
# Instances of the Pressure class can be used to read data from an upstream
|
9
|
+
# provider and broadcast it out to a set of downstream consumers.
|
10
|
+
#
|
11
|
+
# @!attribute [rw] logger
|
12
|
+
# @return [Logger] Messages are logged to this object.
|
13
|
+
# @!attribute [r] sockets
|
14
|
+
# @return [Hamster::Set<#send>] List of downstream sockets the instance is sending
|
15
|
+
# to. These objects don't necessarily need to be sockets, as long as they
|
16
|
+
# support a send method. Add objects to this list using the << method.
|
17
|
+
# @!attribute [rw] wrapper_template
|
18
|
+
# @return [Hash] The template used to wrap upstream data before sending it
|
19
|
+
# to downstream consumers. See wrap_data and the no_wrap option to
|
20
|
+
# initialize.
|
6
21
|
class Pressure
|
7
|
-
|
22
|
+
attr_writer :logger
|
23
|
+
attr_reader :running
|
8
24
|
attr_reader :sockets
|
25
|
+
attr_accessor :wrapper_template
|
26
|
+
|
27
|
+
# The default delay between loops of worker threads.
|
28
|
+
DEFAULT_DELAY = (1.0 / 20.0)
|
9
29
|
|
30
|
+
# Create a new Pressure instance and start reading data.
|
31
|
+
#
|
32
|
+
# @param options [Hash] Additional options.
|
33
|
+
# @option options [Boolean] :no_wrap Data from upstream is wrapped in a JSON
|
34
|
+
# container by default, with some additional metadata. If this option is
|
35
|
+
# set to true, the data will be passed through without modification.
|
36
|
+
# @option options [Float] :read_worker_delay The amount of time, in seconds,
|
37
|
+
# to sleep between attempts to read data from upstream. Defaults to
|
38
|
+
# DEFAULT_DELAY.
|
39
|
+
# @option options [Float] :broadcast_worker_delay The amount of time, in
|
40
|
+
# seconds, to sleep between attempts to broadcast data to downstream
|
41
|
+
# sockets. Defaults to DEFAULT_DELAY.
|
42
|
+
# @yield Block to call to read data from upstream.
|
43
|
+
# @yieldreturn Data to send downstream.
|
10
44
|
def initialize(options = {}, &data_source_block)
|
45
|
+
@threads = []
|
11
46
|
@wrapper_template = {}
|
12
47
|
@current_upstream = {}
|
13
48
|
@send_queue = Queue.new
|
14
|
-
@sockets =
|
15
|
-
@
|
16
|
-
|
49
|
+
@sockets = Hamster::Set.new
|
50
|
+
@broadcast_worker_delay = (options[:broadcast_worker_delay] ||
|
51
|
+
options[:websocket_worker_delay] ||
|
52
|
+
DEFAULT_DELAY)
|
53
|
+
@read_worker_delay = (options[:read_worker_delay] ||
|
54
|
+
options[:incoming_monitor_delay] ||
|
55
|
+
DEFAULT_DELAY)
|
17
56
|
@no_wrap = options[:no_wrap] || false
|
18
|
-
|
19
|
-
|
57
|
+
@running = false
|
58
|
+
@data_source_block = data_source_block
|
59
|
+
start unless options[:start] == false
|
60
|
+
end
|
61
|
+
|
62
|
+
def logger
|
63
|
+
@logger ||= Logger.new(STDERR).tap do |logger|
|
64
|
+
logger.progname = 'pressure'
|
65
|
+
logger.level = Logger::WARN
|
66
|
+
end
|
20
67
|
end
|
21
68
|
|
69
|
+
# Add a downstream socket to the Pressure instance. The latest upstream
|
70
|
+
# data will be immediately sent to the socket.
|
71
|
+
#
|
72
|
+
# @param socket [Socket, #send] A socket, or object that responds to #send.
|
22
73
|
def <<(socket)
|
23
|
-
@sockets
|
24
|
-
|
74
|
+
new_sockets = @sockets.add? socket
|
75
|
+
if new_sockets != false
|
76
|
+
@sockets = new_sockets
|
77
|
+
socket.send JSON.generate(@current_upstream)
|
78
|
+
end
|
25
79
|
end
|
26
80
|
|
81
|
+
# Remove a downstream socket from the Pressure instance.
|
82
|
+
#
|
83
|
+
# @param socket [Socket, #send] A socket, or object that responds to #send,
|
84
|
+
# as added using <<.
|
85
|
+
# @return the deleted socket object, or nil.
|
27
86
|
def delete(socket)
|
28
|
-
@sockets.delete socket
|
87
|
+
new_sockets = @sockets.delete? socket
|
88
|
+
if new_sockets != false
|
89
|
+
@sockets = new_sockets
|
90
|
+
socket
|
91
|
+
else
|
92
|
+
nil
|
93
|
+
end
|
29
94
|
end
|
30
95
|
|
96
|
+
# Start the worker threads.
|
97
|
+
def start
|
98
|
+
stop
|
99
|
+
@running = true
|
100
|
+
@threads << broadcast_worker_loop
|
101
|
+
@threads << read_worker_loop
|
102
|
+
end
|
103
|
+
|
104
|
+
# Stop the worker threads.
|
105
|
+
def stop
|
106
|
+
@running = false
|
107
|
+
@threads.each do |thread|
|
108
|
+
thread.kill(5)
|
109
|
+
thread.join
|
110
|
+
end
|
111
|
+
@threads = []
|
112
|
+
end
|
113
|
+
|
114
|
+
# @return [Boolean] true if the workers are running.
|
115
|
+
def running?
|
116
|
+
@running
|
117
|
+
end
|
118
|
+
|
119
|
+
protected
|
120
|
+
|
121
|
+
# Wraps upstream data in a container to add metadata to the object.
|
122
|
+
#
|
123
|
+
# @param data Upstream data.
|
124
|
+
# @return [Hash] wrapped data.
|
31
125
|
def wrap_data(data)
|
32
126
|
@wrapper_template.merge(upstream_data: Marshal.load(Marshal.dump(data)),
|
33
127
|
last_update_ts: Time.now.utc.to_i)
|
34
128
|
end
|
35
129
|
|
130
|
+
# Check whether two pieces of upstream data are different.
|
131
|
+
#
|
132
|
+
# @param current_data The most recent data read from upstream.
|
133
|
+
# @param previous_data The last set of data read from upstream.
|
134
|
+
# @return [Boolean] true if the data is different.
|
36
135
|
def data_changed?(current_data, previous_data)
|
37
136
|
if current_data && previous_data
|
38
137
|
current_data != previous_data
|
@@ -41,12 +140,13 @@ class Pressure
|
|
41
140
|
end
|
42
141
|
end
|
43
142
|
|
44
|
-
|
143
|
+
# Loop function for the thread reading data from the upstream provider.
|
144
|
+
def read_worker_loop
|
45
145
|
Thread.new do
|
46
146
|
begin
|
47
147
|
data = {}
|
48
|
-
|
49
|
-
upstream_data = data_source_block.call
|
148
|
+
while @running
|
149
|
+
upstream_data = @data_source_block.call
|
50
150
|
if data_changed?(upstream_data, data[:upstream_data])
|
51
151
|
data = wrap_data(upstream_data)
|
52
152
|
@current_upstream = data
|
@@ -56,31 +156,34 @@ class Pressure
|
|
56
156
|
@send_queue << data
|
57
157
|
end
|
58
158
|
end
|
59
|
-
sleep(@
|
159
|
+
sleep(@read_worker_delay)
|
60
160
|
end
|
61
161
|
rescue => e
|
62
|
-
|
162
|
+
logger.error "Read worker error:"
|
163
|
+
logger.error e
|
63
164
|
end
|
64
165
|
end
|
65
166
|
end
|
66
167
|
|
67
|
-
|
68
|
-
|
168
|
+
# Write data to downstream sockets.
|
169
|
+
def broadcast
|
69
170
|
queued_data = JSON.generate(@send_queue.shift)
|
70
171
|
@sockets.each do |socket|
|
71
172
|
socket.send queued_data
|
72
173
|
end
|
73
174
|
end
|
74
175
|
|
75
|
-
|
176
|
+
# Loop function for the thread writing data to the downstream providers.
|
177
|
+
def broadcast_worker_loop
|
76
178
|
Thread.new do
|
77
179
|
begin
|
78
|
-
|
79
|
-
|
80
|
-
sleep(@
|
180
|
+
while @running
|
181
|
+
broadcast
|
182
|
+
sleep(@broadcast_worker_delay)
|
81
183
|
end
|
82
184
|
rescue => e
|
83
|
-
|
185
|
+
logger.error "Broadcast worker error:"
|
186
|
+
logger.error e
|
84
187
|
retry
|
85
188
|
end
|
86
189
|
end
|
data/lib/pressure/version.rb
CHANGED
data/pressure.gemspec
CHANGED
@@ -20,10 +20,15 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ['lib']
|
22
22
|
|
23
|
-
spec.
|
24
|
-
|
23
|
+
spec.add_dependency 'hamster', '~> 3.0'
|
24
|
+
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
26
|
+
spec.add_development_dependency 'rake', '~> 12.3'
|
25
27
|
spec.add_development_dependency 'rspec'
|
26
|
-
spec.add_development_dependency 'redcarpet', '~> 3.
|
27
|
-
spec.add_development_dependency '
|
28
|
-
spec.add_development_dependency '
|
28
|
+
spec.add_development_dependency 'redcarpet', '~> 3.4'
|
29
|
+
spec.add_development_dependency 'simplecov', '~>0.15'
|
30
|
+
spec.add_development_dependency 'sinatra', '~> 2.0'
|
31
|
+
spec.add_development_dependency 'sinatra-websocket', '~> 0.3'
|
32
|
+
spec.add_development_dependency 'timecop', '~> 0.9'
|
33
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
29
34
|
end
|
metadata
CHANGED
@@ -1,43 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pressure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Davidson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hamster
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - "~>"
|
18
32
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
33
|
+
version: '1.16'
|
20
34
|
type: :development
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
40
|
+
version: '1.16'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
47
|
+
version: '12.3'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
54
|
+
version: '12.3'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rspec
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,42 +72,84 @@ dependencies:
|
|
58
72
|
requirements:
|
59
73
|
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '3.
|
75
|
+
version: '3.4'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.4'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.15'
|
62
90
|
type: :development
|
63
91
|
prerelease: false
|
64
92
|
version_requirements: !ruby/object:Gem::Requirement
|
65
93
|
requirements:
|
66
94
|
- - "~>"
|
67
95
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
96
|
+
version: '0.15'
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: sinatra
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
72
100
|
requirements:
|
73
101
|
- - "~>"
|
74
102
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
103
|
+
version: '2.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '2.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: sinatra-websocket
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.3'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.3'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: timecop
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.9'
|
76
132
|
type: :development
|
77
133
|
prerelease: false
|
78
134
|
version_requirements: !ruby/object:Gem::Requirement
|
79
135
|
requirements:
|
80
136
|
- - "~>"
|
81
137
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
138
|
+
version: '0.9'
|
83
139
|
- !ruby/object:Gem::Dependency
|
84
140
|
name: yard
|
85
141
|
requirement: !ruby/object:Gem::Requirement
|
86
142
|
requirements:
|
87
143
|
- - "~>"
|
88
144
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0.
|
145
|
+
version: '0.9'
|
90
146
|
type: :development
|
91
147
|
prerelease: false
|
92
148
|
version_requirements: !ruby/object:Gem::Requirement
|
93
149
|
requirements:
|
94
150
|
- - "~>"
|
95
151
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0.
|
152
|
+
version: '0.9'
|
97
153
|
description:
|
98
154
|
email:
|
99
155
|
- bsdavidson@gmail.com
|
@@ -137,9 +193,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
193
|
version: '0'
|
138
194
|
requirements: []
|
139
195
|
rubyforge_project:
|
140
|
-
rubygems_version: 2.
|
196
|
+
rubygems_version: 2.6.11
|
141
197
|
signing_key:
|
142
198
|
specification_version: 4
|
143
199
|
summary: Multicast upstream data to websocket clients
|
144
200
|
test_files: []
|
145
|
-
has_rdoc:
|