protocol-redis 0.2.0 → 0.3.0

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.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -20,6 +22,6 @@
20
22
 
21
23
  module Protocol
22
24
  module Redis
23
- VERSION = "0.2.0"
25
+ VERSION = "0.3.0"
24
26
  end
25
27
  end
@@ -17,8 +17,10 @@ Gem::Specification.new do |spec|
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.require_paths = ["lib"]
19
19
 
20
+ spec.add_development_dependency "async-http"
21
+ spec.add_development_dependency "trenni"
20
22
  spec.add_development_dependency "benchmark-ips"
21
-
23
+
22
24
  spec.add_development_dependency "covered"
23
25
  spec.add_development_dependency "bundler"
24
26
  spec.add_development_dependency "rspec", "~> 3.6"
@@ -0,0 +1,172 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ # Copyright, 2018, by Huba Nagy.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+
22
+ require 'async'
23
+
24
+ namespace :generate do
25
+ def fetch_commands
26
+ Async do
27
+ internet = Async::HTTP::Internet.new
28
+
29
+ response = internet.get("https://raw.githubusercontent.com/antirez/redis-doc/master/commands.json")
30
+
31
+ JSON.parse(response.read, symbolize_names: true)
32
+ ensure
33
+ internet&.close
34
+ end.wait
35
+ end
36
+
37
+ def normalize(sentence)
38
+ return nil if sentence.nil?
39
+
40
+ sentence = sentence.strip
41
+
42
+ if sentence.end_with?(".")
43
+ return sentence
44
+ else
45
+ return "#{sentence}."
46
+ end
47
+ end
48
+
49
+ def module_name(group)
50
+ group.split('_').collect(&:capitalize).join
51
+ end
52
+
53
+ task :commands do
54
+ require 'async/http/internet'
55
+ require 'json'
56
+
57
+ @commands = fetch_commands
58
+
59
+ @commands.each do |command, command_spec|
60
+ method_name = command.to_s.downcase.split(/[\s\-_]+/).join('_')
61
+ command_spec[:method_name] = method_name
62
+ end
63
+
64
+ # There is a bit of a discrepancy between how the groups appear in the JSON and how they appear in the compiled documentation, this is a mapping from `commands.json` to documentation:
65
+ @groups = {
66
+ 'generic' => 'generic',
67
+ 'string' => 'strings',
68
+ 'list' => 'lists',
69
+ 'set' => 'sets',
70
+ 'sorted_set' => 'sorted_sets',
71
+ 'hash' => 'hashes',
72
+ 'connection' => 'connection',
73
+ 'server' => 'server',
74
+ 'scripting' => 'scripting',
75
+ 'hyperloglog' => 'counting',
76
+ 'cluster' => 'cluster',
77
+ 'geo' => 'geospatial',
78
+ 'stream' => 'streams'
79
+ }.freeze
80
+ end
81
+
82
+ task :methods => :commands do
83
+ require 'trenni/template'
84
+
85
+ template = Trenni::Template.load_file(File.expand_path("methods.trenni", __dir__))
86
+
87
+ @groups.each_pair do |spec_group, group|
88
+ puts "Processing #{spec_group}..."
89
+
90
+ path = "lib/protocol/redis/methods/#{group}.rb"
91
+
92
+ if File.exist?(path)
93
+ puts "File already exists #{path}, skipping!"
94
+ next
95
+ end
96
+
97
+ group_commands = @commands.select do |command, command_spec|
98
+ command_spec[:group] == spec_group
99
+ end
100
+
101
+ output = template.to_string({
102
+ module_name: module_name(group),
103
+ group_commands: group_commands,
104
+ })
105
+
106
+ File.write(path, output)
107
+
108
+ break
109
+ end
110
+ end
111
+
112
+ task :documentation => :commands do
113
+ @groups.each_pair do |spec_group, group|
114
+ puts "Processing #{spec_group}..."
115
+
116
+ path = "lib/protocol/redis/methods/#{group}.rb"
117
+
118
+ unless File.exist?(path)
119
+ puts "Could not find #{path}, skipping!"
120
+ next
121
+ end
122
+
123
+ lines = File.readlines(path)
124
+
125
+ group_commands = @commands.select do |command, command_spec|
126
+ command_spec[:group] == spec_group
127
+ end
128
+
129
+ puts "\tFound #{group_commands.length} commands in this group."
130
+
131
+ group_commands.each do |command, command_spec|
132
+ puts "\tProcessing #{command}..."
133
+
134
+ if offset = lines.find_index{|line| line.include?("def #{command_spec[:method_name]}")}
135
+ puts "Found #{command} at line #{offset}."
136
+
137
+ /(?<indentation>\s+)def/ =~ lines[offset]
138
+
139
+ start = offset
140
+ while true
141
+ break unless lines[start-1] =~ /\s+#(.*?)\n/
142
+ start -= 1
143
+ end
144
+
145
+ # Remove the comments:
146
+ lines.slice!(start...offset)
147
+
148
+ summary = [
149
+ normalize(command_spec[:summary]),
150
+ normalize(command_spec[:complexity])
151
+ ].compact
152
+
153
+ comments = [
154
+ summary.join(' '),
155
+ "@see https://redis.io/commands/#{command.to_s.downcase}"
156
+ ]
157
+
158
+ command_spec[:arguments]&.each do |argument|
159
+ next if argument[:command] or argument[:type].nil? or argument[:type].is_a?(Array)
160
+ comments << "@param #{argument[:name]} [#{argument[:type].capitalize}]"
161
+ end
162
+
163
+ lines.insert(start, comments.map{|comment| "#{indentation}\# #{comment}\n"})
164
+ else
165
+ puts "Could not find #{command} definition!"
166
+ end
167
+ end
168
+
169
+ File.write(path, lines.join)
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module Protocol
24
+ module Redis
25
+ module Methods
26
+ module #{self[:module_name]}
27
+ <?r
28
+ first = true
29
+ self[:group_commands].each do |command, command_spec|
30
+ method_name = command.to_s.downcase.split(/[\s\-_]+/).join('_')
31
+
32
+ unless first
33
+ ?>
34
+
35
+ <?r end ?>
36
+ def #{method_name}(*arguments)
37
+ call(#{command.to_s.dump}, *arguments)
38
+ end
39
+ <?r
40
+ first = false
41
+ end
42
+ ?>
43
+ end
44
+ end
45
+ end
46
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protocol-redis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -9,8 +9,36 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-08-16 00:00:00.000000000 Z
12
+ date: 2019-12-22 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: async-http
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: trenni
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
14
42
  - !ruby/object:Gem::Dependency
15
43
  name: benchmark-ips
16
44
  requirement: !ruby/object:Gem::Requirement
@@ -100,13 +128,18 @@ files:
100
128
  - lib/protocol/redis/connection.rb
101
129
  - lib/protocol/redis/error.rb
102
130
  - lib/protocol/redis/methods.rb
131
+ - lib/protocol/redis/methods/connection.rb
132
+ - lib/protocol/redis/methods/counting.rb
133
+ - lib/protocol/redis/methods/generic.rb
134
+ - lib/protocol/redis/methods/geospatial.rb
103
135
  - lib/protocol/redis/methods/hashes.rb
104
- - lib/protocol/redis/methods/keys.rb
105
136
  - lib/protocol/redis/methods/lists.rb
106
137
  - lib/protocol/redis/methods/server.rb
107
138
  - lib/protocol/redis/methods/strings.rb
108
139
  - lib/protocol/redis/version.rb
109
140
  - protocol-redis.gemspec
141
+ - tasks/generate.rake
142
+ - tasks/methods.trenni
110
143
  homepage: https://github.com/socketry/protocol-redis
111
144
  licenses: []
112
145
  metadata: {}
@@ -125,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
158
  - !ruby/object:Gem::Version
126
159
  version: '0'
127
160
  requirements: []
128
- rubygems_version: 3.0.3
161
+ rubygems_version: 3.0.4
129
162
  signing_key:
130
163
  specification_version: 4
131
164
  summary: A RESP protocol client/server parser.
@@ -1,140 +0,0 @@
1
- # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- # Copyright, 2018, by Huba Nagy.
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in
12
- # all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
-
22
- require 'date'
23
-
24
- module Protocol
25
- module Redis
26
- module Methods
27
- module Keys
28
- def del(key, *keys)
29
- return call('DEL', key, *keys)
30
- end
31
-
32
- def dump(key)
33
- return call('DUMP', key)
34
- end
35
-
36
- def exists(key, *keys)
37
- return call('EXISTS', key, *keys)
38
- end
39
-
40
- def expire(key, seconds)
41
- return call('EXPIRE', key, seconds)
42
- end
43
-
44
- def expireat(key, time)
45
- case time
46
- when DateTime, Time, Date
47
- timestamp = time.strftime('%s').to_i
48
- else
49
- timestamp = time
50
- end
51
-
52
- return call('EXPIREAT', key, timestamp)
53
- end
54
-
55
- def keys(pattern)
56
- return call('KEYS', pattern)
57
- end
58
-
59
- def migrate
60
-
61
- end
62
-
63
- def move(key, db)
64
- return call('MOVE', key, db)
65
- end
66
-
67
- def object
68
-
69
- end
70
-
71
- def persist(key)
72
- return call('PERSIST', key)
73
- end
74
-
75
- def pexpire(key, milliseconds)
76
- return call('PEXPIRE', milliseconds)
77
- end
78
-
79
- def pexpireat(key, time)
80
- case time.class
81
- when DateTime, Time, Date
82
- timestamp = time.strftime('%Q').to_i
83
- else
84
- timestamp = time
85
- end
86
-
87
- return call('PEXPIREAT', key, timestamp)
88
- end
89
-
90
- def pttl(key)
91
- return call('PTTL', key)
92
- end
93
-
94
- def randomkey
95
- return call('RANDOMKEY')
96
- end
97
-
98
- def rename(key, new_key)
99
- return call('RENAME', key, new_key)
100
- end
101
-
102
- def renamenx(key, new_key)
103
- return call('RENAMENX', key, new_key)
104
- end
105
-
106
- def restore(key, serialized_value, ttl=0)
107
- return call('RESTORE', key, ttl, serialized_value)
108
- end
109
-
110
- def sort
111
-
112
- end
113
-
114
- def touch(key, *keys)
115
- return call('TOUCH', key, *keys)
116
- end
117
-
118
- def ttl(key)
119
- return call('TTL', key)
120
- end
121
-
122
- def type(key)
123
- return call('TYPE', key)
124
- end
125
-
126
- def unlink(key)
127
- return call('UNLINK', key)
128
- end
129
-
130
- def wait(newreplicas, timeout)
131
-
132
- end
133
-
134
- def scan
135
-
136
- end
137
- end
138
- end
139
- end
140
- end