protocol-redis 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a084564c0d497c0d149ff2cb4f4109bed1f3e4d59047f629d3a8d38b0fde138
4
- data.tar.gz: 3d3d67b0116b6fba2a1a74f7e3fa23a21a09cb323297ae8891eb16a3613bc4fd
3
+ metadata.gz: e9a0af74e1d169a5d9f8b712a1211deb9c2ab510c969043073e685b5a4d4a99a
4
+ data.tar.gz: 7961d5412651f7969160e5b3844be5ab7db064b5b1f2ff6833ca17e12cc42233
5
5
  SHA512:
6
- metadata.gz: b03f2f6095191cdee5868f7f123c04c9689667f012fca8688f544e21f734a2ab5f3ff4f10fca868085155feed8e38b7a7d97592b32e1aae3b7957d02bfdd7215
7
- data.tar.gz: bf21d0676ba2fac7f4152a0a24bb323bc057e8c201ab5174a0c3db641c0664913f546a658cb227ee3758a8df842d9122eddfe91c49cab5a5fc494eff0d19dae6
6
+ metadata.gz: 6fdf6ab96249d724ea77949cd073cb581f8ad58b96e3d54058e5f2e466ae2de7a947f327b44367a38d65939c2b8d8ed7a72f3e24a408f15871d25c35e45f271a
7
+ data.tar.gz: 27ca946edfed62633623d6876a04cdd36da92b95fbf0e21d5086b493580b1988d4d1a68e9f3ff1f99c1e9da4bc71b812688941b10d799c6dd6060a107c24427a
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in async-io.gemspec
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
3
5
 
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright, 2020, by Samuel G. D. Williams. <http://www.codeotaku.com>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+
24
+ require 'benchmark/ips'
25
+
26
+ GC.disable
27
+
28
+ def call(*arguments)
29
+ arguments.size
30
+ end
31
+
32
+ Benchmark.ips do |benchmark|
33
+ benchmark.time = 5
34
+ benchmark.warmup = 1
35
+
36
+ benchmark.report("*arguments") do |count|
37
+ while count > 0
38
+ arguments = ["foo", "bar", "baz"]
39
+ call(*arguments)
40
+
41
+ count -= 1
42
+ end
43
+ end
44
+
45
+ benchmark.report("argument, *arguments") do |count|
46
+ while count > 0
47
+ arguments = ["bar", "baz"]
48
+ call("foo", *arguments)
49
+
50
+ count -= 1
51
+ end
52
+ end
53
+
54
+ benchmark.compare!
55
+ end
@@ -139,11 +139,11 @@ module Protocol
139
139
  # because each Redis command contains several lines. Flushing once per
140
140
  # command is more efficient because it avoids unnecessary writes to the
141
141
  # socket.
142
- def write_lines(*args)
143
- if args.empty?
142
+ def write_lines(*arguments)
143
+ if arguments.empty?
144
144
  @stream.write(CRLF)
145
145
  else
146
- args.each do |arg|
146
+ arguments.each do |arg|
147
147
  @stream.write(arg)
148
148
  @stream.write(CRLF)
149
149
  end
@@ -30,6 +30,7 @@ require_relative 'methods/counting'
30
30
  require_relative 'methods/hashes'
31
31
  require_relative 'methods/lists'
32
32
  require_relative 'methods/strings'
33
+ require_relative 'methods/sorted_sets'
33
34
 
34
35
  module Protocol
35
36
  module Redis
@@ -44,6 +45,7 @@ module Protocol
44
45
 
45
46
  klass.include Methods::Hashes
46
47
  klass.include Methods::Lists
48
+ klass.include Methods::SortedSets
47
49
  klass.include Methods::Strings
48
50
  end
49
51
  end
@@ -64,21 +64,25 @@ module Protocol
64
64
  # @param latitude [Double]
65
65
  # @param radius [Double]
66
66
  # @param unit [Enum]
67
- # @param withcoord [Enum]
68
- # @param withdist [Enum]
69
- # @param withhash [Enum]
70
- def georadius(key, longitude, latitude, radius, unit = "m", withcoord: false, withdist: false, withhash: false, count: nil, store: nil, storedist: nil)
67
+ # @param count [Integer] Limit the number of results to at most this many.
68
+ # @param order [Symbol] `:ASC` Sort returned items from the nearest to the farthest, relative to the center. `:DESC` Sort returned items from the farthest to the nearest, relative to the center.
69
+ # @param with_coordinates [Boolean] Also return the longitude,latitude coordinates of the matching items.
70
+ # @param with_distance [Boolean] Also return the distance of the returned items from the specified center. The distance is returned in the same unit as the unit specified as the radius argument of the command.
71
+ # @param with_hash [Boolean] Also return the raw geohash-encoded sorted set score of the item, in the form of a 52 bit unsigned integer. This is only useful for low level hacks or debugging and is otherwise of little interest for the general user.
72
+ # @param store [Key]
73
+ # @param store_distance [Key]
74
+ def georadius(key, longitude, latitude, radius, unit = "m", with_coordinates: false, with_distance: false, with_hash: false, count: nil, order: nil, store: nil, store_distance: nil)
71
75
  arguments = [key, longitude, latitude, radius, unit]
72
76
 
73
- if withcoord
77
+ if with_coordinates
74
78
  arguments.append("WITHCOORD")
75
79
  end
76
80
 
77
- if withdist
81
+ if with_distance
78
82
  arguments.append("WITHDIST")
79
83
  end
80
84
 
81
- if withhash
85
+ if with_hash
82
86
  arguments.append("WITHHASH")
83
87
  end
84
88
 
@@ -86,15 +90,28 @@ module Protocol
86
90
  arguments.append("COUNT", count)
87
91
  end
88
92
 
93
+ if order
94
+ arguments.append(order)
95
+ end
96
+
97
+ readonly = true
98
+
89
99
  if store
90
100
  arguments.append("STORE", store)
101
+ readonly = false
91
102
  end
92
103
 
93
- if storedist
104
+ if store_distance
94
105
  arguments.append("STOREDIST", storedist)
106
+ readonly = false
95
107
  end
96
108
 
97
- call("GEORADIUS", *arguments)
109
+ # https://redis.io/commands/georadius#read-only-variants
110
+ if readonly
111
+ call("GEORADIUS_RO", *arguments)
112
+ else
113
+ call("GEORADIUS", *arguments)
114
+ end
98
115
  end
99
116
 
100
117
  # Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a member. O(N+log(M)) where N is the number of elements inside the bounding box of the circular area delimited by center and radius and M is the number of items inside the index.
@@ -103,22 +120,25 @@ module Protocol
103
120
  # @param member [String]
104
121
  # @param radius [Double]
105
122
  # @param unit [Enum]
106
- # @param withcoord [Enum]
107
- # @param withdist [Enum]
108
- # @param withhash [Enum]
109
- # @param order [Enum]
110
- def georadiusbymember(key, member, radius, unit = "m", withcoord: false, withdist: false, withhash: false, count: nil, store: nil, storedist: nil)
123
+ # @param count [Integer] Limit the number of results to at most this many.
124
+ # @param order [Symbol] `:ASC` Sort returned items from the nearest to the farthest, relative to the center. `:DESC` Sort returned items from the farthest to the nearest, relative to the center.
125
+ # @param with_coordinates [Boolean] Also return the longitude,latitude coordinates of the matching items.
126
+ # @param with_distance [Boolean] Also return the distance of the returned items from the specified center. The distance is returned in the same unit as the unit specified as the radius argument of the command.
127
+ # @param with_hash [Boolean] Also return the raw geohash-encoded sorted set score of the item, in the form of a 52 bit unsigned integer. This is only useful for low level hacks or debugging and is otherwise of little interest for the general user.
128
+ # @param store [Key]
129
+ # @param store_distance [Key]
130
+ def georadiusbymember(key, member, radius, unit = "m", with_coordinates: false, with_distance: false, with_hash: false, count: nil, order: nil, store: nil, store_distance: nil)
111
131
  arguments = [key, member, radius, unit]
112
132
 
113
- if withcoord
133
+ if with_coordinates
114
134
  arguments.append("WITHCOORD")
115
135
  end
116
136
 
117
- if withdist
137
+ if with_distance
118
138
  arguments.append("WITHDIST")
119
139
  end
120
140
 
121
- if withhash
141
+ if with_hash
122
142
  arguments.append("WITHHASH")
123
143
  end
124
144
 
@@ -126,15 +146,36 @@ module Protocol
126
146
  arguments.append("COUNT", count)
127
147
  end
128
148
 
149
+ if order
150
+ arguments.append(order)
151
+ end
152
+
129
153
  if store
130
154
  arguments.append("STORE", store)
131
155
  end
132
156
 
133
- if storedist
157
+ if store_distance
134
158
  arguments.append("STOREDIST", storedist)
135
159
  end
136
160
 
137
- call("GEORADIUS", *arguments)
161
+ readonly = true
162
+
163
+ if store
164
+ arguments.append("STORE", store)
165
+ readonly = false
166
+ end
167
+
168
+ if store_distance
169
+ arguments.append("STOREDIST", storedist)
170
+ readonly = false
171
+ end
172
+
173
+ # https://redis.io/commands/georadius#read-only-variants
174
+ if readonly
175
+ call("GEORADIUSBYMEMBER_RO", *arguments)
176
+ else
177
+ call("GEORADIUSBYMEMBER", *arguments)
178
+ end
138
179
  end
139
180
  end
140
181
  end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2020, by Dimitry Chopey.
4
+ # Copyright, 2020, by Samuel G. D. Williams. <http://www.codeotaku.com>
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+
24
+ module Protocol
25
+ module Redis
26
+ module Methods
27
+ module SortedSets
28
+ # Add one or more members to a sorted set, or update its score if it already exists. O(log(N)) for each item added, where N is the number of elements in the sorted set.
29
+ # @see https://redis.io/commands/zadd
30
+ # @param key [Key]
31
+ # @param score [Double]
32
+ # @param member [String]
33
+ # @param others [Array] an array of `score`, `member` elements.
34
+ # @param update [Boolean, nil] If true, only update elements that already exist (never add elements). If false, don't update existing elements (only add new elements).
35
+ # @param change [Boolean] Modify the return value from the number of new elements added,
36
+ # to the total number of elements changed; changed elements are new elements added
37
+ # and elements already existing for which the score was updated.
38
+ # @param increment [Boolean] When this option is specified ZADD acts like ZINCRBY;
39
+ # only one score-element pair can be specified in this mode.
40
+ def zadd(key, score, member, *others, update: nil, change: false, increment: false)
41
+ arguments = ["ZADD", key]
42
+
43
+ if update == true
44
+ arguments << "XX"
45
+ elsif update == false
46
+ arguments << "NX"
47
+ end
48
+
49
+ arguments << "CH" if change
50
+ arguments << "INCR" if increment
51
+
52
+ arguments << score << member
53
+ arguments.concat(others)
54
+
55
+ call(*arguments)
56
+ end
57
+
58
+ # Return a range of members in a sorted set, by index. O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements returned.
59
+ # @see https://redis.io/commands/zrange
60
+ # @param key [Key]
61
+ # @param start [Integer]
62
+ # @param stop [Integer]
63
+ # @param with_scores [Boolean] Return the scores of the elements together with the elements.
64
+ def zrange(key, start, stop, with_scores: false)
65
+ arguments = [start, stop]
66
+
67
+ arguments << "WITHSCORES" if with_scores
68
+
69
+ call("ZRANGE", key, *arguments)
70
+ end
71
+
72
+ # Remove one or more members from a sorted set. O(M*log(N)) with N being the number of elements in the sorted set and M the number of elements to be removed.
73
+ # @see https://redis.io/commands/zrem
74
+ # @param key [Key]
75
+ # @param member [String]
76
+ def zrem(key, member)
77
+ call("ZREM", key, member)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -145,24 +145,22 @@ module Protocol
145
145
  # @param key [Key]
146
146
  # @param value [String]
147
147
  # @param expiration [Enum]
148
- # @param condition [Enum]
149
- def set(key, value, **options)
148
+ # @param update [Boolean, nil] If true, only update elements that already exist (never add elements). If false, don't update existing elements (only add new elements).
149
+ def set(key, value, update: nil, seconds: nil, milliseconds: nil)
150
150
  arguments = []
151
151
 
152
- if options.has_key? :seconds
153
- arguments << 'EX'
154
- arguments << options[:seconds]
152
+ if seconds
153
+ arguments << 'EX' << seconds
155
154
  end
156
155
 
157
- if options.has_key? :milliseconds
158
- arguments << 'PX'
159
- arguments << options[:milliseconds]
156
+ if milliseconds
157
+ arguments << 'PX' << milliseconds
160
158
  end
161
159
 
162
- if options[:condition] == :nx
163
- arguments << 'NX'
164
- elsif options[:condition] == :xx
165
- arguments << 'XX'
160
+ if update == true
161
+ arguments << "XX"
162
+ elsif update == false
163
+ arguments << "NX"
166
164
  end
167
165
 
168
166
  return call('SET', key, value, *arguments)
@@ -22,6 +22,6 @@
22
22
 
23
23
  module Protocol
24
24
  module Redis
25
- VERSION = "0.3.1"
25
+ VERSION = "0.4.0"
26
26
  end
27
27
  end
@@ -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
  # Copyright, 2018, by Huba Nagy.
3
5
  #
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.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-02-07 00:00:00.000000000 Z
12
+ date: 2020-02-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: async-http
@@ -124,6 +124,7 @@ files:
124
124
  - Gemfile
125
125
  - README.md
126
126
  - Rakefile
127
+ - benchmark/call.rb
127
128
  - lib/protocol/redis.rb
128
129
  - lib/protocol/redis/connection.rb
129
130
  - lib/protocol/redis/error.rb
@@ -135,6 +136,7 @@ files:
135
136
  - lib/protocol/redis/methods/hashes.rb
136
137
  - lib/protocol/redis/methods/lists.rb
137
138
  - lib/protocol/redis/methods/server.rb
139
+ - lib/protocol/redis/methods/sorted_sets.rb
138
140
  - lib/protocol/redis/methods/strings.rb
139
141
  - lib/protocol/redis/version.rb
140
142
  - protocol-redis.gemspec