valkey-rb 1.0.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.
- checksums.yaml +7 -0
- data/.rubocop.yml +58 -0
- data/.rubocop_todo.yml +22 -0
- data/README.md +95 -0
- data/Rakefile +23 -0
- data/lib/valkey/bindings.rb +224 -0
- data/lib/valkey/commands/bitmap_commands.rb +86 -0
- data/lib/valkey/commands/cluster_commands.rb +259 -0
- data/lib/valkey/commands/connection_commands.rb +318 -0
- data/lib/valkey/commands/function_commands.rb +255 -0
- data/lib/valkey/commands/generic_commands.rb +525 -0
- data/lib/valkey/commands/geo_commands.rb +87 -0
- data/lib/valkey/commands/hash_commands.rb +587 -0
- data/lib/valkey/commands/hyper_log_log_commands.rb +51 -0
- data/lib/valkey/commands/json_commands.rb +389 -0
- data/lib/valkey/commands/list_commands.rb +348 -0
- data/lib/valkey/commands/module_commands.rb +125 -0
- data/lib/valkey/commands/pubsub_commands.rb +237 -0
- data/lib/valkey/commands/scripting_commands.rb +286 -0
- data/lib/valkey/commands/server_commands.rb +961 -0
- data/lib/valkey/commands/set_commands.rb +220 -0
- data/lib/valkey/commands/sorted_set_commands.rb +971 -0
- data/lib/valkey/commands/stream_commands.rb +636 -0
- data/lib/valkey/commands/string_commands.rb +359 -0
- data/lib/valkey/commands/transaction_commands.rb +175 -0
- data/lib/valkey/commands/vector_search_commands.rb +271 -0
- data/lib/valkey/commands.rb +68 -0
- data/lib/valkey/errors.rb +41 -0
- data/lib/valkey/libglide_ffi.so +0 -0
- data/lib/valkey/opentelemetry.rb +207 -0
- data/lib/valkey/pipeline.rb +20 -0
- data/lib/valkey/protobuf/command_request_pb.rb +51 -0
- data/lib/valkey/protobuf/connection_request_pb.rb +51 -0
- data/lib/valkey/protobuf/response_pb.rb +39 -0
- data/lib/valkey/pubsub_callback.rb +10 -0
- data/lib/valkey/request_error_type.rb +10 -0
- data/lib/valkey/request_type.rb +436 -0
- data/lib/valkey/response_type.rb +20 -0
- data/lib/valkey/utils.rb +253 -0
- data/lib/valkey/version.rb +5 -0
- data/lib/valkey.rb +551 -0
- metadata +119 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Valkey
|
|
4
|
+
module Commands
|
|
5
|
+
# This module contains commands related to Redis Cluster management.
|
|
6
|
+
#
|
|
7
|
+
# @see https://valkey.io/commands/#cluster
|
|
8
|
+
#
|
|
9
|
+
module ClusterCommands
|
|
10
|
+
# Send ASKING command to the server.
|
|
11
|
+
#
|
|
12
|
+
# @return [String] `"OK"`
|
|
13
|
+
def asking
|
|
14
|
+
send_command(RequestType::ASKING)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Add slots to the cluster.
|
|
18
|
+
#
|
|
19
|
+
# @param [Array<Integer>] slots array of slot numbers
|
|
20
|
+
# @return [String] `"OK"`
|
|
21
|
+
def cluster_addslots(*slots)
|
|
22
|
+
send_command(RequestType::CLUSTER_ADD_SLOTS, slots)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Add a range of slots to the cluster.
|
|
26
|
+
#
|
|
27
|
+
# @param [Integer] start_slot starting slot number
|
|
28
|
+
# @param [Integer] end_slot ending slot number
|
|
29
|
+
# @return [String] `"OK"`
|
|
30
|
+
def cluster_addslotsrange(start_slot, end_slot)
|
|
31
|
+
send_command(RequestType::CLUSTER_ADD_SLOTS_RANGE, [start_slot, end_slot])
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Bump the epoch of the cluster.
|
|
35
|
+
#
|
|
36
|
+
# @return [String] `"OK"`
|
|
37
|
+
def cluster_bumpepoch
|
|
38
|
+
send_command(RequestType::CLUSTER_BUMP_EPOCH)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Count failure reports for a node.
|
|
42
|
+
#
|
|
43
|
+
# @param [String] node_id the node ID
|
|
44
|
+
# @return [Integer] number of failure reports
|
|
45
|
+
def cluster_count_failure_reports(node_id)
|
|
46
|
+
send_command(RequestType::CLUSTER_COUNT_FAILURE_REPORTS, [node_id])
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Count keys in a specific slot.
|
|
50
|
+
#
|
|
51
|
+
# @param [Integer] slot the slot number
|
|
52
|
+
# @return [Integer] number of keys in the slot
|
|
53
|
+
def cluster_countkeysinslot(slot)
|
|
54
|
+
send_command(RequestType::CLUSTER_COUNT_KEYS_IN_SLOT, [slot])
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Delete slots from the cluster.
|
|
58
|
+
#
|
|
59
|
+
# @param [Array<Integer>] slots array of slot numbers
|
|
60
|
+
# @return [String] `"OK"`
|
|
61
|
+
def cluster_delslots(*slots)
|
|
62
|
+
send_command(RequestType::CLUSTER_DEL_SLOTS, slots)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Delete a range of slots from the cluster.
|
|
66
|
+
#
|
|
67
|
+
# @param [Integer] start_slot starting slot number
|
|
68
|
+
# @param [Integer] end_slot ending slot number
|
|
69
|
+
# @return [String] `"OK"`
|
|
70
|
+
def cluster_delslotsrange(start_slot, end_slot)
|
|
71
|
+
send_command(RequestType::CLUSTER_DEL_SLOTS_RANGE, [start_slot, end_slot])
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Force a failover of the cluster.
|
|
75
|
+
#
|
|
76
|
+
# @param [String] force force the failover
|
|
77
|
+
# @return [String] `"OK"`
|
|
78
|
+
def cluster_failover(force = nil)
|
|
79
|
+
args = []
|
|
80
|
+
args << "FORCE" if force
|
|
81
|
+
send_command(RequestType::CLUSTER_FAILOVER, args)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Flush all slots from the cluster.
|
|
85
|
+
#
|
|
86
|
+
# @return [String] `"OK"`
|
|
87
|
+
def cluster_flushslots
|
|
88
|
+
send_command(RequestType::CLUSTER_FLUSH_SLOTS)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Remove a node from the cluster.
|
|
92
|
+
#
|
|
93
|
+
# @param [String] node_id the node ID to forget
|
|
94
|
+
# @return [String] `"OK"`
|
|
95
|
+
def cluster_forget(node_id)
|
|
96
|
+
send_command(RequestType::CLUSTER_FORGET, [node_id])
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Get keys in a specific slot.
|
|
100
|
+
#
|
|
101
|
+
# @param [Integer] slot the slot number
|
|
102
|
+
# @param [Integer] count maximum number of keys to return
|
|
103
|
+
# @return [Array<String>] array of keys
|
|
104
|
+
def cluster_getkeysinslot(slot, count)
|
|
105
|
+
send_command(RequestType::CLUSTER_GET_KEYS_IN_SLOT, [slot, count])
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Get information about the cluster.
|
|
109
|
+
#
|
|
110
|
+
# @return [Hash<String, String>] cluster information
|
|
111
|
+
def cluster_info
|
|
112
|
+
send_command(RequestType::CLUSTER_INFO) do |reply|
|
|
113
|
+
Utils::HashifyInfo.call(reply)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Get the slot for a key.
|
|
118
|
+
#
|
|
119
|
+
# @param [String] key the key name
|
|
120
|
+
# @return [Integer] slot number
|
|
121
|
+
def cluster_keyslot(key)
|
|
122
|
+
send_command(RequestType::CLUSTER_KEY_SLOT, [key])
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Get information about cluster links.
|
|
126
|
+
#
|
|
127
|
+
# @return [Array<Hash>] array of link information
|
|
128
|
+
def cluster_links
|
|
129
|
+
send_command(RequestType::CLUSTER_LINKS)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Meet another node in the cluster.
|
|
133
|
+
#
|
|
134
|
+
# @param [String] ip IP address of the node
|
|
135
|
+
# @param [Integer] port port of the node
|
|
136
|
+
# @return [String] `"OK"`
|
|
137
|
+
def cluster_meet(ip, port)
|
|
138
|
+
send_command(RequestType::CLUSTER_MEET, [ip, port])
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Get the ID of the current node.
|
|
142
|
+
#
|
|
143
|
+
# @return [String] node ID
|
|
144
|
+
def cluster_myid
|
|
145
|
+
send_command(RequestType::CLUSTER_MY_ID)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Get the shard ID of the current node.
|
|
149
|
+
#
|
|
150
|
+
# @return [String] shard ID
|
|
151
|
+
def cluster_myshardid
|
|
152
|
+
send_command(RequestType::CLUSTER_MY_SHARD_ID)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Get information about all nodes in the cluster.
|
|
156
|
+
#
|
|
157
|
+
# @return [Array<Hash>] array of node information
|
|
158
|
+
def cluster_nodes
|
|
159
|
+
send_command(RequestType::CLUSTER_NODES) do |reply|
|
|
160
|
+
Utils::HashifyClusterNodes.call(reply)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Get information about replica nodes.
|
|
165
|
+
#
|
|
166
|
+
# @param [String] node_id the master node ID
|
|
167
|
+
# @return [Array<Hash>] array of replica information
|
|
168
|
+
def cluster_replicas(node_id)
|
|
169
|
+
send_command(RequestType::CLUSTER_REPLICAS, [node_id]) do |reply|
|
|
170
|
+
Utils::HashifyClusterSlaves.call(reply)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Set a node as a replica of another node.
|
|
175
|
+
#
|
|
176
|
+
# @param [String] node_id the master node ID
|
|
177
|
+
# @return [String] `"OK"`
|
|
178
|
+
def cluster_replicate(node_id)
|
|
179
|
+
send_command(RequestType::CLUSTER_REPLICATE, [node_id])
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Reset the cluster.
|
|
183
|
+
#
|
|
184
|
+
# @param [String] hard hard reset
|
|
185
|
+
# @return [String] `"OK"`
|
|
186
|
+
def cluster_reset(hard = nil)
|
|
187
|
+
args = []
|
|
188
|
+
args << "HARD" if hard
|
|
189
|
+
send_command(RequestType::CLUSTER_RESET, args)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Save the cluster configuration.
|
|
193
|
+
#
|
|
194
|
+
# @return [String] `"OK"`
|
|
195
|
+
def cluster_saveconfig
|
|
196
|
+
send_command(RequestType::CLUSTER_SAVE_CONFIG)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Set the config epoch for a node.
|
|
200
|
+
#
|
|
201
|
+
# @param [Integer] epoch the config epoch
|
|
202
|
+
# @return [String] `"OK"`
|
|
203
|
+
def cluster_set_config_epoch(epoch)
|
|
204
|
+
send_command(RequestType::CLUSTER_SET_CONFIG_EPOCH, [epoch])
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Set the state of a slot.
|
|
208
|
+
#
|
|
209
|
+
# @param [Integer] slot the slot number
|
|
210
|
+
# @param [String] state the state (importing, migrating, node, stable)
|
|
211
|
+
# @param [String] node_id the node ID (optional)
|
|
212
|
+
# @return [String] `"OK"`
|
|
213
|
+
def cluster_setslot(slot, state, node_id = nil)
|
|
214
|
+
args = [slot, state]
|
|
215
|
+
args << node_id if node_id
|
|
216
|
+
send_command(RequestType::CLUSTER_SETSLOT, args)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Get information about cluster shards.
|
|
220
|
+
#
|
|
221
|
+
# @return [Array<Hash>] array of shard information
|
|
222
|
+
def cluster_shards
|
|
223
|
+
send_command(RequestType::CLUSTER_SHARDS)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Get information about slave nodes (deprecated, use cluster_replicas).
|
|
227
|
+
#
|
|
228
|
+
# @return [Array<Hash>] array of slave information
|
|
229
|
+
def cluster_slaves(node_id)
|
|
230
|
+
send_command(RequestType::CLUSTER_SLAVES, [node_id]) do |reply|
|
|
231
|
+
Utils::HashifyClusterSlaves.call(reply)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Get information about cluster slots.
|
|
236
|
+
#
|
|
237
|
+
# @return [Array<Hash>] array of slot information
|
|
238
|
+
def cluster_slots
|
|
239
|
+
send_command(RequestType::CLUSTER_SLOTS) do |reply|
|
|
240
|
+
Utils::HashifyClusterSlots.call(reply)
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# Set the connection to read-only mode.
|
|
245
|
+
#
|
|
246
|
+
# @return [String] "OK"
|
|
247
|
+
def readonly
|
|
248
|
+
send_command(RequestType::READ_ONLY)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Set the connection to read-write mode.
|
|
252
|
+
#
|
|
253
|
+
# @return [String] "OK"
|
|
254
|
+
def readwrite
|
|
255
|
+
send_command(RequestType::READ_WRITE)
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Valkey
|
|
4
|
+
module Commands
|
|
5
|
+
# This module contains commands related to connection management.
|
|
6
|
+
#
|
|
7
|
+
# @see https://valkey.io/commands/#connection
|
|
8
|
+
#
|
|
9
|
+
module ConnectionCommands
|
|
10
|
+
# Authenticate to the server.
|
|
11
|
+
#
|
|
12
|
+
# @param [Array<String>] args includes both username and password
|
|
13
|
+
# or only password
|
|
14
|
+
# @return [String] `OK`
|
|
15
|
+
def auth(*args)
|
|
16
|
+
send_command(RequestType::AUTH, args)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Ping the server.
|
|
20
|
+
#
|
|
21
|
+
# @param [optional, String] message
|
|
22
|
+
# @return [String] `PONG`
|
|
23
|
+
def ping(message = nil)
|
|
24
|
+
send_command(RequestType::PING, [message].compact)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Echo the given string.
|
|
28
|
+
#
|
|
29
|
+
# @param [String] value
|
|
30
|
+
# @return [String]
|
|
31
|
+
def echo(value)
|
|
32
|
+
send_command(RequestType::ECHO, [value])
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Change the selected database for the current connection.
|
|
36
|
+
#
|
|
37
|
+
# @param [Integer] db zero-based index of the DB to use (0 to 15)
|
|
38
|
+
# @return [String] `OK`
|
|
39
|
+
def select(db)
|
|
40
|
+
send_command(RequestType::SELECT, [db])
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Close the connection.
|
|
44
|
+
#
|
|
45
|
+
# @deprecated The QUIT command is deprecated since Redis 7.2.0 / Valkey 7.2+.
|
|
46
|
+
# Clients should use the `close` method directly instead.
|
|
47
|
+
# This avoids lingering TIME_WAIT sockets on the server side.
|
|
48
|
+
#
|
|
49
|
+
# @return [String] `OK` or nil if connection already closed
|
|
50
|
+
# @see https://redis.io/docs/latest/commands/quit/
|
|
51
|
+
def quit
|
|
52
|
+
# For compatibility, we still support QUIT but recommend using close() instead
|
|
53
|
+
send_command(RequestType::QUIT)
|
|
54
|
+
rescue ConnectionError
|
|
55
|
+
# Server closes connection immediately after QUIT
|
|
56
|
+
nil
|
|
57
|
+
ensure
|
|
58
|
+
# Clean up our side of the connection
|
|
59
|
+
close if respond_to?(:close)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Switch to a different protocol version and handshake with the server.
|
|
63
|
+
#
|
|
64
|
+
# @param [Integer] protover Protocol version (2 or 3)
|
|
65
|
+
# @param [Hash] options Optional parameters like AUTH, SETNAME
|
|
66
|
+
# @return [Array] Server information as flat array (TODO: should be Hash for RESP3)
|
|
67
|
+
def hello(protover = 3, **options)
|
|
68
|
+
args = [protover]
|
|
69
|
+
|
|
70
|
+
if options[:auth]
|
|
71
|
+
args << "AUTH"
|
|
72
|
+
args.concat(Array(options[:auth]))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
args << "SETNAME" << options[:setname] if options[:setname]
|
|
76
|
+
|
|
77
|
+
send_command(RequestType::HELLO, args)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Reset the connection state.
|
|
81
|
+
#
|
|
82
|
+
# @return [String] `RESET`
|
|
83
|
+
def reset
|
|
84
|
+
send_command(RequestType::RESET)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Send a generic CLIENT subcommand.
|
|
88
|
+
#
|
|
89
|
+
# @param [Symbol, String] subcommand The CLIENT subcommand to run, e.g. :list, :id, :kill, etc.
|
|
90
|
+
# @param [Array] args Arguments for the subcommand
|
|
91
|
+
# @return [Object] Depends on subcommand
|
|
92
|
+
# @example
|
|
93
|
+
# client(:id) # => 12345
|
|
94
|
+
# client(:set_name, "my_app") # => "OK"
|
|
95
|
+
# client(:list) # => [{"id" => "1", ...}, ...]
|
|
96
|
+
def client(subcommand, *args)
|
|
97
|
+
send("client_#{subcommand.to_s.downcase}", *args)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Get the current client's ID.
|
|
101
|
+
#
|
|
102
|
+
# @return [Integer] Unique client ID
|
|
103
|
+
def client_id
|
|
104
|
+
send_command(RequestType::CLIENT_ID)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Get the current client's name.
|
|
108
|
+
#
|
|
109
|
+
# @return [String, nil] Client name or nil if not set
|
|
110
|
+
def client_get_name
|
|
111
|
+
send_command(RequestType::CLIENT_GET_NAME)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Set the current client's name.
|
|
115
|
+
#
|
|
116
|
+
# @param [String] name New name for the client connection
|
|
117
|
+
# @return [String] `OK`
|
|
118
|
+
def client_set_name(name)
|
|
119
|
+
send_command(RequestType::CLIENT_SET_NAME, [name])
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Get a list of client connections.
|
|
123
|
+
#
|
|
124
|
+
# @param [String] type Optional filter by client type (normal, master, slave, pubsub)
|
|
125
|
+
# @param [Array<String>] ids Optional filter by client IDs
|
|
126
|
+
# @return [Array<Hash>] List of clients, each represented as a Hash of attributes
|
|
127
|
+
def client_list(type: nil, ids: nil)
|
|
128
|
+
args = []
|
|
129
|
+
|
|
130
|
+
args << "TYPE" << type if type
|
|
131
|
+
|
|
132
|
+
if ids
|
|
133
|
+
args << "ID"
|
|
134
|
+
args.concat(Array(ids))
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
send_command(RequestType::CLIENT_LIST, args) do |reply|
|
|
138
|
+
reply.lines.map do |line|
|
|
139
|
+
entries = line.chomp.split(/[ =]/)
|
|
140
|
+
entries.each_slice(2).to_a.to_h
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Get information about the current client connection.
|
|
146
|
+
#
|
|
147
|
+
# @return [String] Client connection information
|
|
148
|
+
def client_info
|
|
149
|
+
send_command(RequestType::CLIENT_INFO)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Kill client connections.
|
|
153
|
+
#
|
|
154
|
+
# @param [String] addr Client address (ip:port)
|
|
155
|
+
# @param [Hash] options Optional filters (id, type, user, addr, laddr, skipme)
|
|
156
|
+
# @return [Integer] Number of clients killed
|
|
157
|
+
def client_kill(addr = nil, **options)
|
|
158
|
+
if addr && options.empty?
|
|
159
|
+
send_command(RequestType::CLIENT_KILL_SIMPLE, [addr])
|
|
160
|
+
else
|
|
161
|
+
send_command(RequestType::CLIENT_KILL, build_client_kill_args(addr, options))
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Kill a client connection by address (simple form).
|
|
166
|
+
#
|
|
167
|
+
# @param [String] addr Client address (ip:port)
|
|
168
|
+
# @return [String] `OK`
|
|
169
|
+
def client_kill_simple(addr)
|
|
170
|
+
send_command(RequestType::CLIENT_KILL_SIMPLE, [addr])
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
private
|
|
174
|
+
|
|
175
|
+
def build_client_kill_args(addr, options)
|
|
176
|
+
args = []
|
|
177
|
+
args << "ADDR" << addr if addr
|
|
178
|
+
options.each do |key, value|
|
|
179
|
+
case key
|
|
180
|
+
when :id then args << "ID" << value.to_s
|
|
181
|
+
when :type then args << "TYPE" << value.to_s
|
|
182
|
+
when :user then args << "USER" << value.to_s
|
|
183
|
+
when :addr then args << "ADDR" << value.to_s
|
|
184
|
+
when :laddr then args << "LADDR" << value.to_s
|
|
185
|
+
when :skipme then args << "SKIPME" << (value ? "yes" : "no")
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
args
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
public
|
|
192
|
+
|
|
193
|
+
# Pause client processing.
|
|
194
|
+
#
|
|
195
|
+
# @param [Integer] timeout Pause duration in milliseconds
|
|
196
|
+
# @param [String] mode Optional mode (WRITE, ALL)
|
|
197
|
+
# @return [String] `OK`
|
|
198
|
+
def client_pause(timeout, mode = nil)
|
|
199
|
+
args = [timeout]
|
|
200
|
+
args << mode if mode
|
|
201
|
+
send_command(RequestType::CLIENT_PAUSE, args)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Unpause client processing.
|
|
205
|
+
#
|
|
206
|
+
# @return [String] `OK`
|
|
207
|
+
def client_unpause
|
|
208
|
+
send_command(RequestType::CLIENT_UNPAUSE)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Configure client reply mode.
|
|
212
|
+
#
|
|
213
|
+
# @param [String] mode Reply mode (ON, OFF, SKIP)
|
|
214
|
+
# @return [String] `OK`
|
|
215
|
+
def client_reply(mode)
|
|
216
|
+
send_command(RequestType::CLIENT_REPLY, [mode])
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Unblock a client blocked in a blocking operation.
|
|
220
|
+
#
|
|
221
|
+
# @param [Integer] client_id ID of the client to unblock
|
|
222
|
+
# @param [String] unblock_type Optional unblock type (TIMEOUT, ERROR)
|
|
223
|
+
# @return [Integer] 1 if client was unblocked, 0 otherwise
|
|
224
|
+
def client_unblock(client_id, unblock_type = nil)
|
|
225
|
+
args = [client_id]
|
|
226
|
+
args << unblock_type if unblock_type
|
|
227
|
+
send_command(RequestType::CLIENT_UNBLOCK, args)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Set client connection information.
|
|
231
|
+
#
|
|
232
|
+
# @param [String] attr Attribute to set (lib-name, lib-ver)
|
|
233
|
+
# @param [String] value Value to set for the attribute
|
|
234
|
+
# @return [String] `OK`
|
|
235
|
+
def client_set_info(attr, value)
|
|
236
|
+
send_command(RequestType::CLIENT_SET_INFO, [attr, value])
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# Enable/disable client caching.
|
|
240
|
+
#
|
|
241
|
+
# @param [String] mode Caching mode (YES, NO)
|
|
242
|
+
# @return [String] `OK`
|
|
243
|
+
def client_caching(mode)
|
|
244
|
+
send_command(RequestType::CLIENT_CACHING, [mode])
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Configure client tracking.
|
|
248
|
+
#
|
|
249
|
+
# @param [String] status Tracking status (ON, OFF)
|
|
250
|
+
# @param [Array] args Additional positional arguments (REDIRECT, PREFIX, BCAST, OPTIN, OPTOUT, NOLOOP)
|
|
251
|
+
# @param [Hash] options Optional parameters (for keyword argument style)
|
|
252
|
+
# @return [String] `OK`
|
|
253
|
+
# @example Positional style
|
|
254
|
+
# client_tracking("ON", "OPTIN")
|
|
255
|
+
# @example Keyword style
|
|
256
|
+
# client_tracking("ON", optin: true, redirect: 123)
|
|
257
|
+
def client_tracking(status, *args, **options)
|
|
258
|
+
cmd_args = [status]
|
|
259
|
+
cmd_args.concat(args.any? ? args : build_client_tracking_args(options))
|
|
260
|
+
send_command(RequestType::CLIENT_TRACKING, cmd_args)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# Get client tracking information.
|
|
264
|
+
#
|
|
265
|
+
# @return [Array] Tracking information
|
|
266
|
+
def client_tracking_info
|
|
267
|
+
send_command(RequestType::CLIENT_TRACKING_INFO)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Get the client ID used for tracking redirection.
|
|
271
|
+
#
|
|
272
|
+
# @return [Integer] Client ID for tracking redirection
|
|
273
|
+
def client_getredir
|
|
274
|
+
send_command(RequestType::CLIENT_GET_REDIR)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# Enable/disable client no-evict mode.
|
|
278
|
+
#
|
|
279
|
+
# @param [String] mode Mode (ON, OFF)
|
|
280
|
+
# @return [String] `OK`
|
|
281
|
+
def client_no_evict(mode)
|
|
282
|
+
send_command(RequestType::CLIENT_NO_EVICT, [mode.to_s.upcase])
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# Enable/disable client no-touch mode.
|
|
286
|
+
#
|
|
287
|
+
# @param [String] mode Mode (ON, OFF)
|
|
288
|
+
# @return [String] `OK`
|
|
289
|
+
def client_no_touch(mode)
|
|
290
|
+
send_command(RequestType::CLIENT_NO_TOUCH, [mode.to_s.upcase])
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
private
|
|
294
|
+
|
|
295
|
+
def build_client_tracking_args(options)
|
|
296
|
+
args = []
|
|
297
|
+
options.each do |key, value|
|
|
298
|
+
case key
|
|
299
|
+
when :redirect
|
|
300
|
+
args << "REDIRECT" << value.to_s
|
|
301
|
+
when :prefix
|
|
302
|
+
args << "PREFIX"
|
|
303
|
+
Array(value).each { |prefix| args << prefix }
|
|
304
|
+
when :bcast
|
|
305
|
+
args << "BCAST" if value
|
|
306
|
+
when :optin
|
|
307
|
+
args << "OPTIN" if value
|
|
308
|
+
when :optout
|
|
309
|
+
args << "OPTOUT" if value
|
|
310
|
+
when :noloop
|
|
311
|
+
args << "NOLOOP" if value
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
args
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
end
|