rdkit 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b7f8dab0976c2aaf2d8045793c9c52713a7ff867
4
+ data.tar.gz: 0cb9f68b9684fc6c2a5e553202a724396ae75d46
5
+ SHA512:
6
+ metadata.gz: 2e1c7b165b6cc10f382afd74618dd5a5df2a1722e8bbad9a5eb69c2742449fe6f2ca6e39ec0a4b163574b4cce8ae8aaf78a45ccbafddd18e26dc7896e072956d
7
+ data.tar.gz: 2b6889a5764936fb592b0d29418aab64108c7cb53f1b22c2d2e87381a9259e2f8ab7f3f8f4e0e3366a5e554f1399d6a6218b8a28317ed5ef30f7b83ace5a964f
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ script: bundle exec rspec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rdkit.gemspec
4
+ gemspec
@@ -0,0 +1,209 @@
1
+ # RDKit
2
+
3
+ RDKit is a simple toolkit to write Redis-like, single-threaded multiplexing-IO server.
4
+
5
+ The server speaks [Redis RESP protocol](http://redis.io/topics/protocol), so you can reuse many Redis-compatible clients and tools such as:
6
+
7
+ - `redis-cli`
8
+ - `redis-benchmark`
9
+ - [Redic](https://github.com/amakawa/redic)
10
+
11
+ And a lot more.
12
+
13
+ `RDKit` is used to power the [520 Love Radio](http://s.weibo.com/weibo/same%2520%25E7%2594%25B5%25E5%258F%25B0) service of [same.com](http://same.com)
14
+
15
+ [![Code Climate](https://codeclimate.com/github/forresty/rdkit/badges/gpa.svg)](https://codeclimate.com/github/forresty/rdkit)
16
+ [![Build Status](https://travis-ci.org/forresty/rdkit.svg?branch=master)](https://travis-ci.org/forresty/rdkit)
17
+
18
+ ## Installation
19
+
20
+ Add this line to your application's Gemfile:
21
+
22
+ ```ruby
23
+ gem 'rdkit'
24
+ ```
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install rdkit
33
+
34
+ ## Usage
35
+
36
+ see examples under `example` folder.
37
+
38
+ ### Implementing a counter server
39
+
40
+ A simple counter server source code listing:
41
+
42
+ ```ruby
43
+ require 'rdkit'
44
+
45
+ # counter/version.rb
46
+ module Counter
47
+ VERSION = '0.0.1'
48
+ end
49
+
50
+ # counter/core.rb
51
+ module Counter
52
+ class Core < RDKit::Core
53
+ attr_accessor :count
54
+
55
+ def initialize
56
+ @count = 0
57
+ @last_tick = Time.now
58
+ end
59
+
60
+ # `tick!` is called periodically by RDKit
61
+ def tick!
62
+ @last_tick = Time.now
63
+ end
64
+
65
+ def incr(n)
66
+ @count += n
67
+ end
68
+
69
+ def introspection
70
+ {
71
+ counter_version: Counter::VERSION,
72
+ count: @count,
73
+ last_tick: @last_tick
74
+ }
75
+ end
76
+ end
77
+ end
78
+
79
+ # counter/command_runner.rb
80
+ module Counter
81
+ class CommandRunner < RDKit::RESPRunner
82
+ def initialize(counter)
83
+ @counter = counter
84
+ end
85
+
86
+ # every public method of this class will be accessible by clients
87
+ def count
88
+ @counter.count
89
+ end
90
+
91
+ def incr(n=1)
92
+ @counter.incr(n.to_i)
93
+ end
94
+ end
95
+ end
96
+
97
+ # counter/server.rb
98
+ module Counter
99
+ class Server < RDKit::Server
100
+ def initialize
101
+ super('0.0.0.0', 3721)
102
+
103
+ # @core is required by RDKit
104
+ @core = Core.new
105
+
106
+ # @runner is also required by RDKit
107
+ @runner = CommandRunner.new(@core)
108
+ end
109
+
110
+ def introspection
111
+ super.merge(counter: @core.introspection)
112
+ end
113
+ end
114
+ end
115
+
116
+ # start server
117
+
118
+ server = Counter::Server.new
119
+
120
+ trap(:INT) { server.stop }
121
+
122
+ server.start
123
+
124
+ ```
125
+
126
+ ### Connect using `redis-cli`
127
+
128
+ ```shell
129
+ $ redis-cli -p 3721
130
+ 127.0.0.1:3721> count
131
+ (integer) 0
132
+ 127.0.0.1:3721> incr
133
+ (integer) 1
134
+ 127.0.0.1:3721> incr 10
135
+ (integer) 11
136
+ 127.0.0.1:3721> count
137
+ (integer) 11
138
+ 127.0.0.1:3721> info
139
+ # Server
140
+ rdkit_version:0.0.1
141
+ multiplexing_api:select
142
+ process_id:15083
143
+ tcp_port:3721
144
+ uptime_in_seconds:268
145
+ uptime_in_days:0
146
+ hz:10
147
+
148
+ # Clients
149
+ connected_clients:1
150
+ connected_clients_peak:1
151
+
152
+ # Memory
153
+ used_memory_rss:31.89M
154
+ used_memory_peak:31.89M
155
+
156
+ # Counter
157
+ counter_version:0.0.1
158
+ count:11
159
+ last_tick:2015-05-27 20:15:38 +0800
160
+
161
+ # Stats
162
+ total_connections_received:1
163
+ total_commands_processed:6
164
+
165
+ 127.0.0.1:3721> xx
166
+ (error) ERR unknown command 'xx'
167
+ ```
168
+
169
+ ### Benchmarking with `redis-benchmark`
170
+
171
+ ```shell
172
+ $ redis-benchmark -p 3721 incr
173
+ ====== count ======
174
+ 10000 requests completed in 0.73 seconds
175
+ 50 parallel clients
176
+ 3 bytes payload
177
+ keep alive: 1
178
+
179
+ 0.01% <= 1 milliseconds
180
+ 2.27% <= 2 milliseconds
181
+ 42.31% <= 3 milliseconds
182
+ 63.99% <= 4 milliseconds
183
+ 96.14% <= 5 milliseconds
184
+ ...
185
+ 99.97% <= 68 milliseconds
186
+ 99.98% <= 71 milliseconds
187
+ 99.99% <= 74 milliseconds
188
+ 100.00% <= 77 milliseconds
189
+ 13679.89 requests per second
190
+ ```
191
+
192
+ Since it is single-threaded, the count will be correct:
193
+
194
+ ```shell
195
+ 127.0.0.1:3721> count
196
+ (integer) 10000
197
+ ```
198
+
199
+ ## Development
200
+
201
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
202
+
203
+ ## Contributing
204
+
205
+ 1. Fork it ( https://github.com/forresty/rdkit/fork )
206
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
207
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
208
+ 4. Push to the branch (`git push origin my-new-feature`)
209
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rdkit"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,12 @@
1
+ require 'rdkit'
2
+
3
+ require_relative 'counter/version'
4
+ require_relative 'counter/core'
5
+ require_relative 'counter/command_runner'
6
+ require_relative 'counter/server'
7
+
8
+ server = Counter::Server.new
9
+
10
+ trap(:INT) { server.stop }
11
+
12
+ server.start
@@ -0,0 +1,16 @@
1
+ module Counter
2
+ class CommandRunner < RDKit::RESPRunner
3
+ def initialize(counter)
4
+ @counter = counter
5
+ end
6
+
7
+ # every public method of this class will be accessible by clients
8
+ def count
9
+ @counter.count
10
+ end
11
+
12
+ def incr(n=1)
13
+ @counter.incr(n.to_i)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,31 @@
1
+ module Counter
2
+ class Core < RDKit::Core
3
+ attr_accessor :count
4
+
5
+ def initialize
6
+ @count = 0
7
+ @last_tick = Time.now
8
+ end
9
+
10
+ def incr(n)
11
+ @count += n
12
+ end
13
+
14
+ ###########################################
15
+ # overriding required RDKit::Core methods
16
+ ###########################################
17
+
18
+ # `tick!` is called periodically by RDKit
19
+ def tick!
20
+ @last_tick = Time.now
21
+ end
22
+
23
+ def introspection
24
+ {
25
+ counter_version: Counter::VERSION,
26
+ count: @count,
27
+ last_tick: @last_tick
28
+ }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,17 @@
1
+ module Counter
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
+ # @runner is also required by RDKit
10
+ @runner = CommandRunner.new(@core)
11
+ end
12
+
13
+ def introspection
14
+ super.merge(counter: @core.introspection)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Counter
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,10 @@
1
+ require_relative 'rdkit/version'
2
+ require_relative 'rdkit/errors'
3
+ require_relative 'rdkit/resp'
4
+ require_relative 'rdkit/logger'
5
+ require_relative 'rdkit/introspection'
6
+ require_relative 'rdkit/inheritable'
7
+ require_relative 'rdkit/core'
8
+ require_relative 'rdkit/command_parser'
9
+ require_relative 'rdkit/resp_runner'
10
+ require_relative 'rdkit/server'
@@ -0,0 +1,45 @@
1
+ require "hiredis/reader"
2
+ # http://redis.io/topics/protocol
3
+ # Hiredis::Reader does not handle inline commands, so
4
+
5
+ module RDKit
6
+ class CommandParser
7
+ def initialize
8
+ @reader = Hiredis::Reader.new
9
+ @buffer = []
10
+ @regexp = Regexp.new("\\A(.+)\\r\\n\\z")
11
+ @error = nil
12
+ end
13
+
14
+ def feed(data)
15
+ if data =~ @regexp
16
+ @buffer << $1.split
17
+ else
18
+ @reader.feed(data)
19
+
20
+ read_into_buffer!
21
+ end
22
+ end
23
+
24
+ def gets
25
+ raise @error unless @error.nil?
26
+
27
+ if result = @buffer.shift
28
+
29
+ result
30
+ else
31
+ @reader.gets
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def read_into_buffer!
38
+ until (reply = @reader.gets) == false
39
+ @buffer << reply
40
+ end
41
+ rescue RuntimeError => e
42
+ @error = ProtocolError.new(e) if e.message =~ /Protocol error/
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,13 @@
1
+ module RDKit
2
+ class Core
3
+ include Inheritable
4
+
5
+ def tick!
6
+ raise ShouldOverrideError
7
+ end
8
+
9
+ def introspection
10
+ raise ShouldOverrideError
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module RDKit
2
+ class RDKitError < StandardError; end
3
+
4
+ class ProtocolError < RDKitError; end
5
+ class UnknownCommandError < ProtocolError; end
6
+ class WrongNumberOfArgumentError < ProtocolError; end
7
+
8
+ class NotImplementedError < RDKitError; end
9
+
10
+ class SDKRequirementNotMetError < RDKitError; end
11
+ class ShouldOverrideError < SDKRequirementNotMetError; end
12
+ end
@@ -0,0 +1,15 @@
1
+ module RDKit
2
+ module Inheritable
3
+ def self.included(base)
4
+ base.instance_eval do
5
+ def instance(*args)
6
+ @subclass.new(*args)
7
+ end
8
+
9
+ def inherited(klass)
10
+ @subclass = klass
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,82 @@
1
+ # 127.0.0.1:6379> info
2
+ # # Server
3
+ # redis_version:2.8.17
4
+ # redis_git_sha1:00000000
5
+ # redis_git_dirty:0
6
+ # redis_build_id:32eb139b4f2b63
7
+ # redis_mode:standalone
8
+ # os:Darwin 13.4.0 x86_64
9
+ # arch_bits:64
10
+ # multiplexing_api:kqueue
11
+ # gcc_version:4.2.1
12
+ # process_id:471
13
+ # run_id:efa5b449cc3ba9c53f7bbb159a773e6ff20d575c
14
+ # tcp_port:6379
15
+ # uptime_in_seconds:1510124
16
+ # uptime_in_days:17
17
+ # hz:10
18
+ #
19
+ # # Clients
20
+ # connected_clients:1
21
+ # client_longest_output_list:0
22
+ # client_biggest_input_buf:0
23
+ #
24
+ # # Memory
25
+ # used_memory:124510288
26
+ # used_memory_human:118.74M
27
+ # used_memory_rss:119885824
28
+ # used_memory_peak:124510288
29
+ # used_memory_peak_human:118.74M
30
+ # used_memory_lua:33792
31
+ # mem_fragmentation_ratio:0.96
32
+ # mem_allocator:libc
33
+ #
34
+ # # Persistence
35
+ #
36
+ # # Stats
37
+ # total_connections_received:74408
38
+ # total_commands_processed:5122851
39
+ # instantaneous_ops_per_sec:0
40
+ # rejected_connections:0
41
+ # pubsub_channels:0
42
+ # pubsub_patterns:0
43
+
44
+ module RDKit
45
+ module Introspection
46
+ class Stats
47
+ attr_reader :data
48
+
49
+ def initialize
50
+ @data = {}
51
+
52
+ @data.default = 0
53
+ end
54
+
55
+ module ClassMethods
56
+ @@instance = Stats.new
57
+
58
+ def incr(key)
59
+ @@instance.data[key] += 1
60
+ end
61
+
62
+ def info
63
+ @@instance.data
64
+ end
65
+ end
66
+
67
+ class << self; include ClassMethods; end
68
+ end
69
+
70
+ module ClassMethods
71
+ def register(server)
72
+ @@server = server
73
+ end
74
+
75
+ def info
76
+ @@server.introspection.merge({ stats: Stats.info })
77
+ end
78
+ end
79
+
80
+ class << self; include ClassMethods; end
81
+ end
82
+ end
@@ -0,0 +1,27 @@
1
+ module RDKit
2
+ class Logger
3
+ def debug(message)
4
+ return unless $DEBUG && ENV['RACK_ENV'] != 'test'
5
+
6
+ log(message)
7
+ end
8
+
9
+ def info(message)
10
+ log(message)
11
+ end
12
+
13
+ def warn(message)
14
+ log(message)
15
+ end
16
+
17
+ def log(message)
18
+ case message
19
+ when StandardError
20
+ puts message.inspect
21
+ puts message.backtrace.join("\n")
22
+ else
23
+ puts message
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ # http://redis.io/topics/protocol
2
+
3
+ module RDKit
4
+ class RESP
5
+ module ClassMethods
6
+ def compose(data)
7
+ case data
8
+ when Integer
9
+ ":#{data}\r\n"
10
+ when Array
11
+ "*#{data.size}\r\n" + data.map { |i| compose(i) }.join
12
+ when NilClass
13
+ # Null Bulk String, not Null Array of "*-1\r\n"
14
+ "$-1\r\n"
15
+ when StandardError
16
+ "-#{data.message}\r\n"
17
+ else
18
+ # always Bulk String
19
+ "$#{data.bytesize}\r\n#{data}\r\n"
20
+ end
21
+ end
22
+ end
23
+
24
+ class << self; include ClassMethods; end
25
+ end
26
+ end
@@ -0,0 +1,46 @@
1
+ module RDKit
2
+ class RESPRunner
3
+ include Inheritable
4
+
5
+ def resp(cmd)
6
+ RESP.compose(call(cmd))
7
+ rescue => e
8
+ RESP.compose(e)
9
+ end
10
+
11
+ # 获取服务器状态
12
+ def info
13
+ Introspection.info.map do |type, value|
14
+ "# #{type.capitalize}\r\n" + value.map { |k, v| "#{k}:#{v}" }.join("\r\n") + "\r\n"
15
+ end.join("\r\n") + "\r\n"
16
+ end
17
+
18
+ private
19
+
20
+ def call(cmd)
21
+ @logger ||= Logger.new
22
+
23
+ Introspection::Stats.incr(:total_commands_processed)
24
+
25
+ @logger.debug "running command: #{cmd}"
26
+ cmd, *args = cmd
27
+
28
+ cmd.downcase!
29
+
30
+ if self.respond_to?(cmd)
31
+ self.__send__(cmd, *args)
32
+ else
33
+ raise UnknownCommandError, "ERR unknown command '#{cmd}'"
34
+ end
35
+ rescue ArgumentError => e
36
+ raise WrongNumberOfArgumentError, "ERR wrong number of arguments for '#{cmd}' command"
37
+ end
38
+
39
+ module RedisCompatibility
40
+ def select(id); 'OK'; end
41
+ def ping; 'PONG'; end
42
+ end
43
+
44
+ include RedisCompatibility
45
+ end
46
+ end
@@ -0,0 +1,192 @@
1
+ require 'newrelic_rpm'
2
+
3
+ module RDKit
4
+ class Server
5
+ HZ = 10
6
+ CYCLES_TIL_MEMORY_RESAMPLE = 1000
7
+
8
+ attr_reader :server_up_since
9
+ attr_reader :runner
10
+ attr_reader :core
11
+ attr_reader :host, :port
12
+
13
+ def initialize(host, port)
14
+ @host, @port = host, port
15
+
16
+ @cycles = 0
17
+ @peak_memory = 0
18
+ @peak_connected_clients = 0
19
+
20
+ @clients, @command_parsers = Hash.new, Hash.new
21
+
22
+ @logger = Logger.new
23
+
24
+ Introspection.register(self)
25
+
26
+ @server_up_since = Time.now
27
+ end
28
+
29
+ def sanity_check!
30
+ unless @host && @port
31
+ raise SDKRequirementNotMetError, '@host and @port are required for server to run'
32
+ end
33
+
34
+ if @core.nil?
35
+ raise SDKRequirementNotMetError, '@core is required to represent your business logics'
36
+ end
37
+
38
+ if @runner.nil?
39
+ raise SDKRequirementNotMetError, '@runner is required to act as an RESP frontend'
40
+ end
41
+ end
42
+
43
+ def start
44
+ sanity_check!
45
+
46
+ @server_socket = TCPServer.new(@host, @port)
47
+
48
+ run_acceptor
49
+ end
50
+
51
+ def stop
52
+ @logger.warn "signal caught, shutting down..."
53
+ exit
54
+ end
55
+
56
+ def introspection
57
+ {
58
+ server: {
59
+ rdkit_version: RDKit::VERSION,
60
+ multiplexing_api: 'select',
61
+ process_id: Process.pid,
62
+ tcp_port: @port,
63
+ uptime_in_seconds: (Time.now - @server_up_since).to_i,
64
+ uptime_in_days: ((Time.now - @server_up_since) / (24 * 60 * 60)).to_i,
65
+ hz: HZ,
66
+ },
67
+ clients: {
68
+ connected_clients: @clients.size,
69
+ connected_clients_peak: @peak_connected_clients
70
+ },
71
+ memory: {
72
+ used_memory_rss: used_memory_rss_in_mb,
73
+ used_memory_peak: used_memory_peak_in_mb
74
+ },
75
+ }
76
+ end
77
+
78
+ private
79
+
80
+ def used_memory_rss_in_mb
81
+ update_peak_memory!
82
+
83
+ '%0.2f' % used_memory_rss + 'M'
84
+ end
85
+
86
+ def used_memory_peak_in_mb
87
+ '%0.2f' % @peak_memory + 'M'
88
+ end
89
+
90
+ def add_client
91
+ Introspection::Stats.incr(:total_connections_received)
92
+
93
+ socket = @server_socket.accept_nonblock
94
+
95
+ @command_parsers[socket] = CommandParser.new
96
+
97
+ @clients[socket] = Fiber.new do
98
+ with_error_handling(socket) do |io|
99
+ loop { process(io); Fiber.yield }
100
+ end
101
+ end
102
+
103
+ @logger.debug "client #{socket} connected"
104
+
105
+ return @clients[socket]
106
+ end
107
+
108
+ def process(io)
109
+ feed_parser(io)
110
+
111
+ until (reply = get_parser_reply(io)) == false
112
+ send_response(io, reply)
113
+ end
114
+ end
115
+
116
+ def feed_parser(io)
117
+ cmd = io.readpartial(1024)
118
+
119
+ @command_parsers[io].feed(cmd)
120
+ end
121
+
122
+ def get_parser_reply(io)
123
+ @command_parsers[io].gets
124
+ end
125
+
126
+ def send_response(io, cmd)
127
+ resp = runner.resp(cmd)
128
+
129
+ @logger.debug(resp)
130
+
131
+ io.write(resp)
132
+ end
133
+
134
+ def with_error_handling(socket, &block)
135
+
136
+ block.call(socket)
137
+
138
+ rescue Errno::ECONNRESET, EOFError => e
139
+ # client disconnected
140
+ @logger.debug "client #{socket.inspect} has disconnected"
141
+ @logger.debug e
142
+ @command_parsers.delete(socket)
143
+ @clients.delete(socket)
144
+ rescue ProtocolError => e
145
+ # client protocol error, force disconnect
146
+ @logger.debug "client protocol error"
147
+ @logger.debug e
148
+ socket.close
149
+ @command_parsers.delete(socket)
150
+ @clients.delete(socket)
151
+ end
152
+
153
+ def run_acceptor
154
+ @logger.info "accepting on shared socket (#{@host}:#{@port})"
155
+
156
+ loop do
157
+ readable, _ = IO.select([@server_socket, @clients.keys].flatten, nil, nil, 1.0 / HZ)
158
+
159
+ if readable
160
+ readable.each do |socket|
161
+ if socket == @server_socket
162
+ add_client
163
+ else
164
+ # client is a Fiber
165
+ client = @clients[socket]
166
+ client.resume
167
+ end
168
+ end
169
+ end
170
+
171
+ update_peak_memory! if @cycles % CYCLES_TIL_MEMORY_RESAMPLE == 0
172
+ update_peak_connected_clients!
173
+
174
+ @cycles += 1
175
+
176
+ core.tick!
177
+ end
178
+ end
179
+
180
+ def update_peak_memory!
181
+ @peak_memory = [@peak_memory, used_memory_rss].max
182
+ end
183
+
184
+ def update_peak_connected_clients!
185
+ @peak_connected_clients = [@peak_connected_clients, @clients.size].max
186
+ end
187
+
188
+ def used_memory_rss
189
+ NewRelic::Agent::Samplers::MemorySampler.new.sampler.get_sample
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,3 @@
1
+ module RDKit
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rdkit/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rdkit"
8
+ spec.version = RDKit::VERSION
9
+ spec.authors = ["Forrest Ye"]
10
+ spec.email = ["afu@forresty.com"]
11
+
12
+ spec.summary = %q{RDKit is a simple toolkit to write Redis-like, single-threaded multiplexing-IO server.}
13
+ spec.homepage = "http://github.com/forresty/rdkit"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ spec.bindir = "exe"
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_runtime_dependency 'hiredis'
21
+ spec.add_runtime_dependency 'newrelic_rpm'
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.8"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rspec"
26
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rdkit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Forrest Ye
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-05-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: hiredis
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: newrelic_rpm
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description:
84
+ email:
85
+ - afu@forresty.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".travis.yml"
93
+ - Gemfile
94
+ - README.md
95
+ - Rakefile
96
+ - bin/console
97
+ - bin/setup
98
+ - example/counter.rb
99
+ - example/counter/command_runner.rb
100
+ - example/counter/core.rb
101
+ - example/counter/server.rb
102
+ - example/counter/version.rb
103
+ - lib/rdkit.rb
104
+ - lib/rdkit/command_parser.rb
105
+ - lib/rdkit/core.rb
106
+ - lib/rdkit/errors.rb
107
+ - lib/rdkit/inheritable.rb
108
+ - lib/rdkit/introspection.rb
109
+ - lib/rdkit/logger.rb
110
+ - lib/rdkit/resp.rb
111
+ - lib/rdkit/resp_runner.rb
112
+ - lib/rdkit/server.rb
113
+ - lib/rdkit/version.rb
114
+ - rdkit.gemspec
115
+ homepage: http://github.com/forresty/rdkit
116
+ licenses: []
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 2.4.5
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: RDKit is a simple toolkit to write Redis-like, single-threaded multiplexing-IO
138
+ server.
139
+ test_files: []