rdkit 0.0.1 → 0.1.4
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/.gitignore +3 -0
- data/Gemfile +10 -1
- data/Gemfile.ci +13 -0
- data/Guardfile +40 -0
- data/README.md +282 -6
- data/Vagrantfile +13 -0
- data/example/blocking.rb +10 -0
- data/example/blocking/command_runner.rb +28 -0
- data/example/blocking/core.rb +24 -0
- data/example/blocking/server.rb +10 -0
- data/example/blocking/version.rb +3 -0
- data/example/callbacks.rb +9 -0
- data/example/callbacks/command_runner.rb +21 -0
- data/example/callbacks/core.rb +18 -0
- data/example/callbacks/server.rb +30 -0
- data/example/counter.rb +0 -2
- data/example/counter/command_runner.rb +4 -0
- data/example/counter/core.rb +4 -0
- data/example/http.rb +9 -0
- data/example/http/core.rb +18 -0
- data/example/http/responder.rb +7 -0
- data/example/http/server.rb +19 -0
- data/lib/rdkit.rb +20 -3
- data/lib/rdkit/callbacks.rb +10 -0
- data/lib/rdkit/client.rb +157 -0
- data/lib/rdkit/configuration.rb +31 -0
- data/lib/rdkit/core.rb +2 -4
- data/lib/rdkit/core_ext.rb +7 -0
- data/lib/rdkit/db.rb +257 -0
- data/lib/rdkit/db_commands.rb +182 -0
- data/lib/rdkit/errors.rb +32 -1
- data/lib/rdkit/http_parser.rb +56 -0
- data/lib/rdkit/http_responder.rb +74 -0
- data/lib/rdkit/introspection.rb +133 -21
- data/lib/rdkit/logger.rb +9 -4
- data/lib/rdkit/memory_monitoring.rb +29 -0
- data/lib/rdkit/notification_center.rb +21 -0
- data/lib/rdkit/rd_object.rb +69 -0
- data/lib/rdkit/resp.rb +9 -1
- data/lib/rdkit/{command_parser.rb → resp_parser.rb} +6 -18
- data/lib/rdkit/resp_responder.rb +105 -0
- data/lib/rdkit/server.rb +242 -86
- data/lib/rdkit/simple_commands.rb +17 -0
- data/lib/rdkit/slow_log.rb +52 -0
- data/lib/rdkit/subcommands.rb +157 -0
- data/lib/rdkit/version.rb +1 -1
- data/rdkit.gemspec +6 -0
- metadata +119 -5
- data/lib/rdkit/inheritable.rb +0 -15
- data/lib/rdkit/resp_runner.rb +0 -46
@@ -0,0 +1,28 @@
|
|
1
|
+
module Blocking
|
2
|
+
class CommandRunner < RDKit::RESPRunner
|
3
|
+
attr_reader :core
|
4
|
+
|
5
|
+
def initialize(core)
|
6
|
+
@core = core
|
7
|
+
end
|
8
|
+
|
9
|
+
def block_with_callback
|
10
|
+
core.block_with_callback
|
11
|
+
|
12
|
+
# this is ignored, instead `on_success` block of `core.block_with_callback` is evaluated and returned
|
13
|
+
'OK'
|
14
|
+
end
|
15
|
+
|
16
|
+
def block
|
17
|
+
core.block
|
18
|
+
|
19
|
+
'OK'
|
20
|
+
end
|
21
|
+
|
22
|
+
def nonblock
|
23
|
+
core.nonblock
|
24
|
+
|
25
|
+
'OK'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Blocking
|
2
|
+
class Core < RDKit::Core
|
3
|
+
def block_with_callback
|
4
|
+
on_success = lambda { 'success' }
|
5
|
+
|
6
|
+
server.blocking(on_success) { do_something }
|
7
|
+
end
|
8
|
+
|
9
|
+
def block
|
10
|
+
server.blocking { do_something }
|
11
|
+
end
|
12
|
+
|
13
|
+
def nonblock
|
14
|
+
do_something
|
15
|
+
end
|
16
|
+
|
17
|
+
def do_something
|
18
|
+
sleep 1
|
19
|
+
end
|
20
|
+
|
21
|
+
def tick!
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Callbacks
|
2
|
+
class Server < RDKit::Server
|
3
|
+
def initialize
|
4
|
+
super('0.0.0.0', 3721)
|
5
|
+
|
6
|
+
@core = Core.new
|
7
|
+
@runner = CommandRunner.new(core)
|
8
|
+
end
|
9
|
+
|
10
|
+
def client_connected(client)
|
11
|
+
puts "client_connected: #{client.id}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def client_disconnected(client)
|
15
|
+
puts "client_disconnected: #{client.id}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def client_command_processed(client)
|
19
|
+
puts "client_command_processed: #{client.id}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def client_block_resumed(client)
|
23
|
+
puts "client_block_resumed: #{client.id}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def client_blocked(client)
|
27
|
+
puts "client_blocked: #{client.id}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/example/counter.rb
CHANGED
data/example/counter/core.rb
CHANGED
data/example/http.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module HTTP
|
2
|
+
class Core < RDKit::Core
|
3
|
+
def initialize
|
4
|
+
@last_tick = Time.now
|
5
|
+
end
|
6
|
+
|
7
|
+
# `tick!` is called periodically by RDKit
|
8
|
+
def tick!
|
9
|
+
@last_tick = Time.now
|
10
|
+
end
|
11
|
+
|
12
|
+
def introspection
|
13
|
+
{
|
14
|
+
last_tick: @last_tick
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module HTTP
|
2
|
+
class Server < RDKit::Server
|
3
|
+
def initialize
|
4
|
+
super('0.0.0.0', 3721)
|
5
|
+
|
6
|
+
# @core is required by RDKit
|
7
|
+
@core = Core.new
|
8
|
+
|
9
|
+
# @responder is also required by RDKit
|
10
|
+
@responder = Responder.new
|
11
|
+
|
12
|
+
@parser_class = RDKit::HTTPParser
|
13
|
+
end
|
14
|
+
|
15
|
+
def introspection
|
16
|
+
super.merge(counter: @core.introspection)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/rdkit.rb
CHANGED
@@ -1,10 +1,27 @@
|
|
1
1
|
require_relative 'rdkit/version'
|
2
|
+
require_relative 'rdkit/core_ext'
|
2
3
|
require_relative 'rdkit/errors'
|
4
|
+
require_relative 'rdkit/configuration'
|
5
|
+
require_relative 'rdkit/notification_center'
|
6
|
+
require_relative 'rdkit/slow_log'
|
3
7
|
require_relative 'rdkit/resp'
|
4
8
|
require_relative 'rdkit/logger'
|
5
9
|
require_relative 'rdkit/introspection'
|
6
|
-
require_relative 'rdkit/inheritable'
|
7
10
|
require_relative 'rdkit/core'
|
8
|
-
|
9
|
-
require_relative 'rdkit/
|
11
|
+
|
12
|
+
require_relative 'rdkit/resp_parser'
|
13
|
+
require_relative 'rdkit/http_parser'
|
14
|
+
|
15
|
+
require_relative 'rdkit/simple_commands'
|
16
|
+
require_relative 'rdkit/rd_object'
|
17
|
+
require_relative 'rdkit/db_commands'
|
18
|
+
require_relative 'rdkit/subcommands'
|
19
|
+
|
20
|
+
require_relative 'rdkit/resp_responder'
|
21
|
+
require_relative 'rdkit/http_responder'
|
22
|
+
|
23
|
+
require_relative 'rdkit/client'
|
24
|
+
require_relative 'rdkit/memory_monitoring'
|
25
|
+
require_relative 'rdkit/db'
|
26
|
+
require_relative 'rdkit/callbacks'
|
10
27
|
require_relative 'rdkit/server'
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module RDKit
|
2
|
+
module Callbacks
|
3
|
+
def server_started; end
|
4
|
+
def client_connected(client); end
|
5
|
+
def client_disconnected(client); end
|
6
|
+
def client_command_processed(client); end
|
7
|
+
def client_block_resumed(client); end
|
8
|
+
def client_blocked(client); end
|
9
|
+
end
|
10
|
+
end
|
data/lib/rdkit/client.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'thread/future'
|
2
|
+
|
3
|
+
module RDKit
|
4
|
+
class Client
|
5
|
+
attr_accessor :id
|
6
|
+
attr_accessor :name
|
7
|
+
attr_accessor :fd
|
8
|
+
attr_accessor :last_command
|
9
|
+
attr_reader :socket
|
10
|
+
|
11
|
+
def initialize(socket, server)
|
12
|
+
@server = server
|
13
|
+
@socket = socket
|
14
|
+
@responder = server.responder
|
15
|
+
@command_parser = server.parser_class.new
|
16
|
+
@logger = server.logger
|
17
|
+
@created_at = Time.now
|
18
|
+
@last_interacted_at = Time.now
|
19
|
+
|
20
|
+
@fiber = Fiber.new do
|
21
|
+
with_error_handling(socket) do |io|
|
22
|
+
loop { process; Fiber.yield }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def resume
|
28
|
+
@last_interacted_at = Time.now
|
29
|
+
|
30
|
+
@fiber.resume
|
31
|
+
end
|
32
|
+
|
33
|
+
def blocking(on_success=nil, &block)
|
34
|
+
@blocked_at = Time.now
|
35
|
+
|
36
|
+
@on_block_success = on_success
|
37
|
+
|
38
|
+
@future = Thread.future(@server.pool) { block.call }
|
39
|
+
end
|
40
|
+
|
41
|
+
def finished?
|
42
|
+
@future.delivered?
|
43
|
+
end
|
44
|
+
|
45
|
+
def unblock!
|
46
|
+
Introspection::Commandstats.record("bg_#{last_command}", ((Time.now - @blocked_at) * 1_000_000).to_i)
|
47
|
+
|
48
|
+
@blocked_at = nil
|
49
|
+
|
50
|
+
@server.client_block_resumed(self)
|
51
|
+
@fiber.resume
|
52
|
+
end
|
53
|
+
|
54
|
+
def info
|
55
|
+
{
|
56
|
+
id: @id,
|
57
|
+
addr: socket_addr,
|
58
|
+
fd: @socket.fileno,
|
59
|
+
name: @name,
|
60
|
+
age: age,
|
61
|
+
idle: idle,
|
62
|
+
cmd: @last_command
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def socket_addr
|
67
|
+
@socket.remote_address.inspect_sockaddr
|
68
|
+
end
|
69
|
+
|
70
|
+
def name=(name)
|
71
|
+
# http://www.asciitable.com
|
72
|
+
# `networking.c` in redis source code
|
73
|
+
name.each_char { |c| raise IllegalClientNameError unless c >= '!' && c <= '~' }
|
74
|
+
|
75
|
+
@name = name
|
76
|
+
end
|
77
|
+
|
78
|
+
def kill!
|
79
|
+
@socket.close
|
80
|
+
@server.delete(@socket)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def age
|
86
|
+
(Time.now - @created_at).to_i
|
87
|
+
end
|
88
|
+
|
89
|
+
def idle
|
90
|
+
(Time.now - @last_interacted_at).to_i
|
91
|
+
end
|
92
|
+
|
93
|
+
def with_error_handling(socket, &block)
|
94
|
+
|
95
|
+
block.call(socket)
|
96
|
+
|
97
|
+
rescue IOError, Errno::ECONNRESET, EOFError => e
|
98
|
+
# client disconnected
|
99
|
+
@logger.debug "client #{socket.inspect} has disconnected"
|
100
|
+
@logger.debug e
|
101
|
+
|
102
|
+
raise ClientDisconnectedError
|
103
|
+
rescue ProtocolError => e
|
104
|
+
# client protocol error, force disconnect
|
105
|
+
@logger.debug "client protocol error"
|
106
|
+
@logger.debug e
|
107
|
+
|
108
|
+
raise ClientDisconnectedError
|
109
|
+
end
|
110
|
+
|
111
|
+
def process
|
112
|
+
feed_parser
|
113
|
+
|
114
|
+
until (reply = get_parser_reply) == false
|
115
|
+
execute_and_send_response(reply)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def feed_parser
|
120
|
+
cmd = @socket.readpartial(1024)
|
121
|
+
|
122
|
+
Introspection::Stats.incr(:total_net_input_bytes, cmd.bytesize)
|
123
|
+
|
124
|
+
@command_parser.feed(cmd)
|
125
|
+
end
|
126
|
+
|
127
|
+
def get_parser_reply
|
128
|
+
@command_parser.gets
|
129
|
+
end
|
130
|
+
|
131
|
+
def execute_and_send_response(cmd)
|
132
|
+
@last_command = cmd.first
|
133
|
+
|
134
|
+
@server.monitors.each do |client|
|
135
|
+
msg = "+#{Time.now.to_f} [#{socket_addr}] #{ cmd.map { |c| %Q{"#{c}"}}.join(' ') }\r\n"
|
136
|
+
|
137
|
+
client.socket.write(msg)
|
138
|
+
end
|
139
|
+
|
140
|
+
resp, usec = SlowLog.monitor(cmd) { @responder.run(cmd) }
|
141
|
+
|
142
|
+
if @blocked_at
|
143
|
+
@server.client_blocked(self)
|
144
|
+
Fiber.yield
|
145
|
+
|
146
|
+
resp = @responder.run(@on_block_success) if @on_block_success
|
147
|
+
end
|
148
|
+
|
149
|
+
Introspection::Commandstats.record(cmd.first, usec)
|
150
|
+
Introspection::Stats.incr(:total_net_output_bytes, resp.bytesize)
|
151
|
+
|
152
|
+
@logger.debug(resp)
|
153
|
+
|
154
|
+
@socket.write(resp)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|