nchan_tools 0.1.11 → 0.1.12
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/exe/nchan-redis-debug +15 -5
- data/lib/nchan_tools/rdsck.rb +123 -3
- data/lib/nchan_tools/version.rb +1 -1
- data/nchan_tools.gemspec +2 -0
- metadata +31 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c506959c2eba296db96ed5e1598412798117f4e33bae4a909e223148a829b4a
|
4
|
+
data.tar.gz: 4f178a9eac6fa954d06b5f9f4d6d21cb5c3e6320390e3f422fdcb0589e5276d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 183363cebe229289e9c3eb0c0989a2816b7bb06c2f3650a81fdad8b5a22c1a2502bd182081a49bbcdf076d0eef219f0ae8f3ccff6a31252e8a137d1940347231
|
7
|
+
data.tar.gz: e5c09c1e6759dd835fb9699a96e63e6d2bbb7ae7adefac324cae19083f0921d3699fc88bdeb54dde4810153ed9cf528d22f9829688c8f9a02fb2f547f507debf
|
data/exe/nchan-redis-debug
CHANGED
@@ -15,14 +15,19 @@ opt_parser=OptionParser.new do |opts|
|
|
15
15
|
opt[:url]=v
|
16
16
|
end
|
17
17
|
opts.on("-q", "--quiet", "output only results without any other information") do
|
18
|
-
opt[:quiet]=
|
19
|
-
opts[:verbose] = !opt[:quiet]
|
18
|
+
opt[:quiet]=true
|
20
19
|
end
|
21
20
|
opts.on("--list-channels", "list all Nchan channels on Redis server or cluster") do |v|
|
22
21
|
opt[:command]=:filter_channels
|
23
22
|
end
|
23
|
+
opts.on("--watch-channels", "watch for changes in Nchan channels on Redis server or cluster") do |v|
|
24
|
+
opt[:command]=:watch_channels
|
25
|
+
end
|
26
|
+
opts.on("--set-notify-keyspace-events", "when using --watch-channels, sets the notify-keyspace-events Redis config before starting. May not be possible if the redis 'config' command is disabled") do
|
27
|
+
opt[:set_notify_keyspace_events] = true
|
28
|
+
end
|
24
29
|
opts.on("--filter-channels-min-subscribers=[NUMBER]") do |v|
|
25
|
-
opt[:command]
|
30
|
+
opt[:command]||=:filter_channels
|
26
31
|
opt[:min_subscribers]=v.to_i
|
27
32
|
end
|
28
33
|
end
|
@@ -40,6 +45,8 @@ opt_parser.banner= <<~EOB
|
|
40
45
|
EOB
|
41
46
|
opt_parser.parse!
|
42
47
|
|
48
|
+
opt[:verbose] = !opt[:quiet]
|
49
|
+
|
43
50
|
rdsck = Rdsck.new opt
|
44
51
|
if not rdsck.connect
|
45
52
|
STDERR.puts "failed to connect to #{opt[:url]}"
|
@@ -48,10 +55,13 @@ end
|
|
48
55
|
|
49
56
|
case opt[:command]
|
50
57
|
when :filter_channels
|
51
|
-
|
58
|
+
rdsck.dbg "scanning for channels #{opt[:min_subscribers] && "with subscribers >= #{opt[:min_subscribers]}"}"
|
52
59
|
chans = rdsck.filter_channels(min_subscribers: opt[:min_subscribers])
|
53
|
-
|
60
|
+
rdsck.dbg "found #{chans.count} channel#{chans.count != 1 && "s"}#{chans.count == 0 ? "." : ":"}"
|
54
61
|
puts chans.join("\n")
|
62
|
+
when :watch_channels
|
63
|
+
rdsck.dbg "watching for channels #{opt[:min_subscribers] && "with subscribers >= #{opt[:min_subscribers]}"}"
|
64
|
+
rdsck.watch_channels({min_subscribers: opt[:min_subscribers]}, opt[:set_notify_keyspace_events])
|
55
65
|
else
|
56
66
|
puts "Nothing to do"
|
57
67
|
end
|
data/lib/nchan_tools/rdsck.rb
CHANGED
@@ -1,4 +1,40 @@
|
|
1
1
|
class Rdsck
|
2
|
+
require "async"
|
3
|
+
require "async/redis"
|
4
|
+
|
5
|
+
#doesn't support psubscribe by default. can you believe it?!
|
6
|
+
class Async::Redis::Context::Psubscribe < Async::Redis::Context::Subscribe
|
7
|
+
MESSAGE = 'pmessage'
|
8
|
+
|
9
|
+
def listen
|
10
|
+
while response = @connection.read_response
|
11
|
+
return response if response.first == MESSAGE
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def subscribe(channels)
|
16
|
+
@connection.write_request ['PSUBSCRIBE', *channels]
|
17
|
+
@connection.flush
|
18
|
+
end
|
19
|
+
|
20
|
+
def unsubscribe(channels)
|
21
|
+
@connection.write_request ['PUNSUBSCRIBE', *channels]
|
22
|
+
@connection.flush
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Async::Redis::Client
|
27
|
+
def psubscribe(*channels)
|
28
|
+
context = Async::Redis::Context::Psubscribe.new(@pool, channels)
|
29
|
+
return context unless block_given?
|
30
|
+
begin
|
31
|
+
yield context
|
32
|
+
ensure
|
33
|
+
context.close
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
2
38
|
attr_accessor :url, :verbose, :namespace
|
3
39
|
attr_accessor :redis, :masters
|
4
40
|
|
@@ -22,9 +58,10 @@ class Rdsck
|
|
22
58
|
|
23
59
|
def connect
|
24
60
|
begin
|
25
|
-
puts "connect to #{@url}"
|
26
61
|
@redis=Redis.new url: @url
|
62
|
+
|
27
63
|
mode = redis.info["redis_mode"]
|
64
|
+
|
28
65
|
rescue StandardError => e
|
29
66
|
STDERR.puts e.message
|
30
67
|
return false
|
@@ -33,7 +70,6 @@ class Rdsck
|
|
33
70
|
if mode == "cluster"
|
34
71
|
@redis.close
|
35
72
|
begin
|
36
|
-
puts "cluster-connect to #{@url}"
|
37
73
|
@redis=Redis.new cluster: [@url]
|
38
74
|
@redis.ping
|
39
75
|
rescue StandardError => e
|
@@ -71,6 +107,90 @@ class Rdsck
|
|
71
107
|
#...
|
72
108
|
end
|
73
109
|
|
110
|
+
class Watch
|
111
|
+
def initialize(rdsck, node, filters, set_notify_config = nil)
|
112
|
+
@rdsck = rdsck
|
113
|
+
@sync = node
|
114
|
+
@filters = filters
|
115
|
+
@set_notify_config = set_notify_config
|
116
|
+
@host, @port, @location = @sync.connection[:host], @sync.connection[:port]
|
117
|
+
@url = @sync.connection[:id]
|
118
|
+
@async = Async::Redis::Client.new(Async::IO::Endpoint.tcp(@host, @port))
|
119
|
+
if set_notify_config
|
120
|
+
@rdsck.dbg "set #{@url} notify-keyspace-events to \"Kh\""
|
121
|
+
@prev_notify_keyspace_event_config = @sync.config("get", "notify-keyspace-events")
|
122
|
+
@prev_notify_keyspace_event_config = @prev_notify_keyspace_event_config[1] if @prev_notify_keyspace_event_config
|
123
|
+
|
124
|
+
@sync.config :set, "notify-keyspace-events", "Kh"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def watch(task)
|
129
|
+
task.async do
|
130
|
+
#puts "subscribeme"
|
131
|
+
while true do
|
132
|
+
@async.psubscribe "__keyspace*__:{channel:*}" do |ctx|
|
133
|
+
type, pattern, name, msg = ctx.listen
|
134
|
+
#puts "TYPE: #{type}, PAT:#{pattern}, NAME:#{name}, MSG:#{msg}"
|
135
|
+
m=name.match(/^__.*__:(\{.*\})/)
|
136
|
+
if m && m[1]
|
137
|
+
key = m[1]
|
138
|
+
|
139
|
+
filtered = false
|
140
|
+
subs = nil
|
141
|
+
|
142
|
+
if @filters[:min_subscribers]
|
143
|
+
subs = @sync.hget key, "fake_subscribers"
|
144
|
+
subs = subs.to_i
|
145
|
+
filtered = true if subs < @filters[:min_subscribers]
|
146
|
+
end
|
147
|
+
|
148
|
+
if !filtered
|
149
|
+
if subs
|
150
|
+
puts "#{key} subscribers: #{subs}"
|
151
|
+
else
|
152
|
+
puts "#{key}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def stop
|
163
|
+
@async.close
|
164
|
+
if @set_notify_config
|
165
|
+
@rdsck.dbg "set #{@url} notify-keyspace-events back to #{@prev_notify_keyspace_event_config}"
|
166
|
+
@sync.config(:set, "notify-keyspace-events", @prev_notify_keyspace_event_config)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def watch_channels(filters={}, set_notify_keyspace_events=nil)
|
172
|
+
watchers = []
|
173
|
+
@masters.each do |m|
|
174
|
+
watchers << Watch.new(self, m, filters, set_notify_keyspace_events)
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
begin
|
179
|
+
Async do |task|
|
180
|
+
watchers.each do |watcher|
|
181
|
+
watcher.watch(task)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
rescue Interrupt => e
|
185
|
+
dbg "stopping watch"
|
186
|
+
ensure
|
187
|
+
watchers.each do |watcher|
|
188
|
+
watcher.stop
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
74
194
|
def filter_channels(filters={})
|
75
195
|
script = <<~EOF
|
76
196
|
local prev_cursor = ARGV[1]
|
@@ -102,7 +222,7 @@ class Rdsck
|
|
102
222
|
|
103
223
|
results = []
|
104
224
|
batch_size=500
|
105
|
-
masters.each do |m|
|
225
|
+
@masters.each do |m|
|
106
226
|
hash = m.script "load", script
|
107
227
|
cursor, pattern = "0", "{channel:*}"
|
108
228
|
loop do
|
data/lib/nchan_tools/version.rb
CHANGED
data/nchan_tools.gemspec
CHANGED
@@ -30,6 +30,8 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_dependency "celluloid-io"
|
31
31
|
spec.add_dependency "HDRHistogram"
|
32
32
|
spec.add_dependency "redis", "~>4.2.0"
|
33
|
+
spec.add_dependency "async"
|
34
|
+
spec.add_dependency "async-redis"
|
33
35
|
|
34
36
|
spec.add_dependency "websocket-driver"
|
35
37
|
spec.add_dependency 'websocket-extensions'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nchan_tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leo Ponomarev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: typhoeus
|
@@ -108,6 +108,34 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: 4.2.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: async
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: async-redis
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
111
139
|
- !ruby/object:Gem::Dependency
|
112
140
|
name: websocket-driver
|
113
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -268,7 +296,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
268
296
|
- !ruby/object:Gem::Version
|
269
297
|
version: '0'
|
270
298
|
requirements: []
|
271
|
-
rubygems_version: 3.
|
299
|
+
rubygems_version: 3.2.7
|
272
300
|
signing_key:
|
273
301
|
specification_version: 4
|
274
302
|
summary: Development and testing utilities for Nchan
|