Module: Valkey::Commands::GenericCommands

Included in:
Valkey::Commands
Defined in:
lib/valkey/commands/generic_commands.rb

Overview

this module contains generic commands that are not specific to any data type

Instance Method Summary collapse

Instance Method Details

#_scan(command, cursor, args, match: nil, count: nil, type: nil, &block) ⇒ Object



521
522
523
524
525
526
527
528
529
530
# File 'lib/valkey/commands/generic_commands.rb', line 521

def _scan(command, cursor, args, match: nil, count: nil, type: nil, &block)
  # SSCAN/ZSCAN/HSCAN already prepend the key to +args+.

  args << cursor
  args << "MATCH" << match if match
  args << "COUNT" << Integer(count) if count
  args << "TYPE" << type if type

  send_command(command, args, &block)
end

#call(*argv, **kwargs) ⇒ Object

Send any command as plain arguments and get the raw reply back, with no per-command method needed. Escape hatch for commands without a dedicated method yet, matching redis-client's #call.

Examples:

Basic dispatch

valkey.call("SET", "mykey", "value")
  # => "OK"

Integers/Floats auto-stringify

valkey.call("SET", "mykey", 42)
  # equivalent to call("SET", "mykey", "42")

Arrays flatten

valkey.call("LPUSH", "list", [1, 2, 3])
  # equivalent to call("LPUSH", "list", "1", "2", "3")

Hashes flatten to alternating key/value

valkey.call("HMSET", "hash", { "foo" => "1" })
  # equivalent to call("HMSET", "hash", "foo", "1")

Keyword args become command flags; falsy/nil flags are dropped

valkey.call("SET", "k", "v", nx: true, ex: 60)
  # equivalent to call("SET", "k", "v", "NX", "EX", "60")

Parameters:

  • argv (Array<String, Integer, Float, Array, Hash>)

    command name and its arguments

  • kwargs (Hash)

    trailing command flags; truthy values emit the upcased flag name, non-boolean values also emit the stringified value; falsy/nil values are dropped

Returns:

  • (Object)

    the raw reply, with no type-casting based on the command name

See Also:



558
559
560
# File 'lib/valkey/commands/generic_commands.rb', line 558

def call(*argv, **kwargs)
  send_command(RequestType::CUSTOM_COMMAND, flatten_call_args(argv).concat(call_flags(kwargs)))
end

#call_v(argv) ⇒ Object

Send any command as a single Array of arguments and get the raw reply back. Same as #call but takes the whole command as one Array instead of splatted args, useful when the command is built dynamically. Matches redis-client's #call_v — no keyword flags.

Examples:

valkey.call_v(["MGET"] + keys)

Parameters:

  • argv (Array<String, Integer, Float, Array, Hash>)

    command name and its arguments

Returns:

  • (Object)

    the raw reply, with no type-casting based on the command name

See Also:



574
575
576
# File 'lib/valkey/commands/generic_commands.rb', line 574

def call_v(argv)
  send_command(RequestType::CUSTOM_COMMAND, flatten_call_args(argv))
end

#copy(source, destination, db: nil, replace: false) ⇒ Boolean

Copy a value from one key to another.

Examples:

Copy a value to another key

valkey.set "foo", "value"
  # => "OK"
valkey.copy "foo", "bar"
  # => true
valkey.get "bar"
  # => "value"

Copy a value to a key in another database

valkey.set "foo", "value"
  # => "OK"
valkey.copy "foo", "bar", db: 2
  # => true
valkey.select 2
  # => "OK"
valkey.get "bar"
  # => "value"

Parameters:

  • source (String)
  • destination (String)
  • db (Integer) (defaults to: nil)
  • replace (Boolean) (defaults to: false)

    removes the destination key before copying value to it

Returns:

  • (Boolean)

    whether the key was copied or not



376
377
378
379
380
381
382
# File 'lib/valkey/commands/generic_commands.rb', line 376

def copy(source, destination, db: nil, replace: false)
  args = [source, destination]
  args << "DB" << db if db
  args << "REPLACE" if replace

  send_command(RequestType::COPY, args)
end

#del(*keys) ⇒ Integer

Delete one or more keys.

Parameters:

  • keys (String, Array<String>)

Returns:

  • (Integer)

    number of keys that were deleted



297
298
299
300
301
302
# File 'lib/valkey/commands/generic_commands.rb', line 297

def del(*keys)
  keys.flatten!(1)
  return 0 if keys.empty?

  send_command(RequestType::DEL, keys)
end

#dump(key) ⇒ String

Return a serialized version of the value stored at a key.

Parameters:

  • key (String)

Returns:

  • (String)

    serialized_value



213
214
215
# File 'lib/valkey/commands/generic_commands.rb', line 213

def dump(key)
  send_command(RequestType::DUMP, [key])
end

#exists(*keys) ⇒ Integer

Determine how many of the keys exists.

Parameters:

  • keys (String, Array<String>)

Returns:

  • (Integer)


316
317
318
# File 'lib/valkey/commands/generic_commands.rb', line 316

def exists(*keys)
  send_command(RequestType::EXISTS, keys.flatten)
end

#exists?(*keys) ⇒ Boolean

Determine if any of the keys exists.

Parameters:

  • keys (String, Array<String>)

Returns:

  • (Boolean)


324
325
326
# File 'lib/valkey/commands/generic_commands.rb', line 324

def exists?(*keys)
  send_command(RequestType::EXISTS, keys.flatten, &:positive?)
end

#expire(key, seconds, nx: nil, xx: nil, gt: nil, lt: nil) ⇒ Boolean

Set a key's time to live in seconds.

Parameters:

  • key (String)
  • seconds (Integer)

    time to live

  • options (Hash)
    • :nx => true: Set expiry only when the key has no expiry.
    • :xx => true: Set expiry only when the key has an existing expiry.
    • :gt => true: Set expiry only when the new expiry is greater than current one.
    • :lt => true: Set expiry only when the new expiry is less than current one.

Returns:

  • (Boolean)

    whether the timeout was set or not



92
93
94
95
96
97
98
99
100
# File 'lib/valkey/commands/generic_commands.rb', line 92

def expire(key, seconds, nx: nil, xx: nil, gt: nil, lt: nil)
  args = [key, Integer(seconds)]
  args << "NX" if nx
  args << "XX" if xx
  args << "GT" if gt
  args << "LT" if lt

  send_command(RequestType::EXPIRE, args)
end

#expireat(key, unix_time, nx: nil, xx: nil, gt: nil, lt: nil) ⇒ Boolean

Set the expiration for a key as a UNIX timestamp.

Parameters:

  • key (String)
  • unix_time (Integer)

    expiry time specified as a UNIX timestamp

  • options (Hash)
    • :nx => true: Set expiry only when the key has no expiry.
    • :xx => true: Set expiry only when the key has an existing expiry.
    • :gt => true: Set expiry only when the new expiry is greater than current one.
    • :lt => true: Set expiry only when the new expiry is less than current one.

Returns:

  • (Boolean)

    whether the timeout was set or not



112
113
114
115
116
117
118
119
120
# File 'lib/valkey/commands/generic_commands.rb', line 112

def expireat(key, unix_time, nx: nil, xx: nil, gt: nil, lt: nil)
  args = [key, Integer(unix_time)]
  args << "NX" if nx
  args << "XX" if xx
  args << "GT" if gt
  args << "LT" if lt

  send_command(RequestType::EXPIRE_AT, args)
end

#expiretime(key) ⇒ Integer

Get a key's expiry time specified as number of seconds from UNIX Epoch

Parameters:

  • key (String)

Returns:

  • (Integer)

    expiry time specified as number of seconds from UNIX Epoch



126
127
128
# File 'lib/valkey/commands/generic_commands.rb', line 126

def expiretime(key)
  send_command(RequestType::EXPIRE_TIME, [key])
end

#keys(pattern = "*") ⇒ Array<String>

Find all keys matching the given pattern.

Examples:

Find all keys

valkey.keys
  # => ["key1", "key2", ...]

Find keys matching a pattern

valkey.keys("user:*")
  # => ["user:1", "user:2"]

Parameters:

  • pattern (String) (defaults to: "*")

    glob-style pattern (default: "*")

Returns:

  • (Array<String>)

    array of matching keys

See Also:



283
284
285
286
287
288
289
290
291
# File 'lib/valkey/commands/generic_commands.rb', line 283

def keys(pattern = "*")
  send_command(RequestType::KEYS, [pattern]) do |reply|
    if reply.is_a?(String)
      reply.split
    else
      reply
    end
  end
end

#migrate(key, options) ⇒ String

Transfer a key from the connected instance to another instance.

Examples:

Migrate a single key

valkey.migrate("mykey", host: "127.0.0.1", port: 6380)
  # => "OK"

Migrate with copy and replace

valkey.migrate("mykey", host: "127.0.0.1", port: 6380, copy: true, replace: true)
  # => "OK"

Migrate multiple keys

valkey.migrate(["key1", "key2"], host: "127.0.0.1", port: 6380)
  # => "OK"

Parameters:

  • key (String, Array<String>)

    single key or array of keys to migrate

  • options (Hash)
    • :host => String: host of instance to migrate to (required)
    • :port => Integer: port of instance to migrate to (required)
    • :db => Integer: database to migrate to (default: 0)
    • :timeout => Integer: timeout in milliseconds (default: 0)
    • :copy => Boolean: do not remove the key from the local instance
    • :replace => Boolean: replace existing key on the remote instance

Returns:

  • (String)

    "OK"

See Also:



256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/valkey/commands/generic_commands.rb', line 256

def migrate(key, options)
  args = []
  args << (options[:host] || raise(ArgumentError, ':host not specified'))
  args << (options[:port] || raise(ArgumentError, ':port not specified')).to_s
  args << (key.is_a?(String) ? key : '')
  args << (options[:db] || 0).to_s
  args << (options[:timeout] || 0).to_s
  args << 'COPY' if options[:copy]
  args << 'REPLACE' if options[:replace]
  args += ['KEYS', *key] if key.is_a?(Array)

  send_command(RequestType::MIGRATE, args)
end

#move(key, db) ⇒ Boolean

Move a key to another database.

Examples:

Move a key to another database

valkey.set "foo", "bar"
  # => "OK"
valkey.move "foo", 2
  # => true
valkey.exists "foo"
  # => false
valkey.select 2
  # => "OK"
valkey.exists "foo"
  # => true
valkey.get "foo"
  # => "bar"

Parameters:

  • key (String)
  • db (Integer)

Returns:

  • (Boolean)

    whether the key was moved or not



347
348
349
# File 'lib/valkey/commands/generic_commands.rb', line 347

def move(key, db)
  send_command(RequestType::MOVE, [key, db])
end

#object(subcommand, *args) ⇒ Object



384
385
386
387
388
389
390
391
392
393
# File 'lib/valkey/commands/generic_commands.rb', line 384

def object(subcommand, *args)
  map = {
    refcount: RequestType::OBJECT_REF_COUNT,
    encoding: RequestType::OBJECT_ENCODING,
    idletime: RequestType::OBJECT_IDLE_TIME,
    freq: RequestType::OBJECT_FREQ
  }

  send_command(map[subcommand.to_sym], args.flatten)
end

#persist(key) ⇒ Boolean

Remove the expiration from a key.

Parameters:

  • key (String)

Returns:

  • (Boolean)

    whether the timeout was removed or not



78
79
80
# File 'lib/valkey/commands/generic_commands.rb', line 78

def persist(key)
  send_command(RequestType::PERSIST, [key])
end

#pexpire(key, milliseconds, nx: nil, xx: nil, gt: nil, lt: nil) ⇒ Boolean

Set a key's time to live in milliseconds.

Parameters:

  • key (String)
  • milliseconds (Integer)

    time to live

  • options (Hash)
    • :nx => true: Set expiry only when the key has no expiry.
    • :xx => true: Set expiry only when the key has an existing expiry.
    • :gt => true: Set expiry only when the new expiry is greater than current one.
    • :lt => true: Set expiry only when the new expiry is less than current one.

Returns:

  • (Boolean)

    whether the timeout was set or not



156
157
158
159
160
161
162
163
164
# File 'lib/valkey/commands/generic_commands.rb', line 156

def pexpire(key, milliseconds, nx: nil, xx: nil, gt: nil, lt: nil)
  args = [key, Integer(milliseconds)]
  args << "NX" if nx
  args << "XX" if xx
  args << "GT" if gt
  args << "LT" if lt

  send_command(RequestType::PEXPIRE, args)
end

#pexpireat(key, ms_unix_time, nx: nil, xx: nil, gt: nil, lt: nil) ⇒ Boolean

Set the expiration for a key as number of milliseconds from UNIX Epoch.

Parameters:

  • key (String)
  • ms_unix_time (Integer)

    expiry time specified as number of milliseconds from UNIX Epoch.

  • options (Hash)
    • :nx => true: Set expiry only when the key has no expiry.
    • :xx => true: Set expiry only when the key has an existing expiry.
    • :gt => true: Set expiry only when the new expiry is greater than current one.
    • :lt => true: Set expiry only when the new expiry is less than current one.

Returns:

  • (Boolean)

    whether the timeout was set or not



176
177
178
179
180
181
182
183
184
# File 'lib/valkey/commands/generic_commands.rb', line 176

def pexpireat(key, ms_unix_time, nx: nil, xx: nil, gt: nil, lt: nil)
  args = [key, Integer(ms_unix_time)]
  args << "NX" if nx
  args << "XX" if xx
  args << "GT" if gt
  args << "LT" if lt

  send_command(RequestType::PEXPIRE_AT, args)
end

#pexpiretime(key) ⇒ Integer

Get a key's expiry time specified as number of milliseconds from UNIX Epoch

Parameters:

  • key (String)

Returns:

  • (Integer)

    expiry time specified as number of milliseconds from UNIX Epoch



190
191
192
# File 'lib/valkey/commands/generic_commands.rb', line 190

def pexpiretime(key)
  send_command(RequestType::PEXPIRE_TIME, [key])
end

#pttl(key) ⇒ Integer

Get the time to live (in milliseconds) for a key.

In valkey 2.6 or older the command returns -1 if the key does not exist or if the key exist but has no associated expire.

Starting with valkey 2.8 the return value in case of error changed:

- The command returns -2 if the key does not exist.
- The command returns -1 if the key exists but has no associated expire.

Parameters:

  • key (String)

Returns:

  • (Integer)

    remaining time to live in milliseconds



205
206
207
# File 'lib/valkey/commands/generic_commands.rb', line 205

def pttl(key)
  send_command(RequestType::PTTL, [key])
end

#randomkeyString

Return a random key from the keyspace.

Returns:

  • (String)


398
399
400
# File 'lib/valkey/commands/generic_commands.rb', line 398

def randomkey
  send_command(RequestType::RANDOM_KEY)
end

#rename(old_name, new_name) ⇒ String

Rename a key. If the new key already exists it is overwritten.

Parameters:

  • old_name (String)
  • new_name (String)

Returns:

  • (String)

    OK



407
408
409
# File 'lib/valkey/commands/generic_commands.rb', line 407

def rename(old_name, new_name)
  send_command(RequestType::RENAME, [old_name, new_name])
end

#renamenx(old_name, new_name) ⇒ Boolean

Rename a key, only if the new key does not exist.

Parameters:

  • old_name (String)
  • new_name (String)

Returns:

  • (Boolean)

    whether the key was renamed or not



416
417
418
# File 'lib/valkey/commands/generic_commands.rb', line 416

def renamenx(old_name, new_name)
  send_command(RequestType::RENAME_NX, [old_name, new_name])
end

#restore(key, ttl, serialized_value, replace: nil) ⇒ String

Create a key using the serialized value, previously obtained using DUMP.

Parameters:

  • key (String)
  • ttl (String)
  • serialized_value (String)
  • options (Hash)
    • :replace => Boolean: if false, raises an error if key already exists

Returns:

  • (String)

    "OK"

Raises:

  • (valkey::CommandError)


226
227
228
229
230
231
# File 'lib/valkey/commands/generic_commands.rb', line 226

def restore(key, ttl, serialized_value, replace: nil)
  args = [key, ttl, serialized_value]
  args << 'REPLACE' if replace

  send_command(RequestType::RESTORE, args)
end

#scan(cursor, **options) ⇒ String+

Note:

Standalone mode only. glide-core has no defined default route for SCAN in cluster mode, so each call may land on a different node with no cursor continuity between them — results are undefined (missed or duplicated keys) rather than merely partial.

Scan the keyspace

Examples:

Retrieve the first batch of keys

valkey.scan(0)
  # => ["4", ["key:21", "key:47", "key:42"]]

Retrieve a batch of keys matching a pattern

valkey.scan(4, :match => "key:1?")
  # => ["92", ["key:13", "key:18"]]

Retrieve a batch of keys of a certain type

valkey.scan(92, :type => "zset")
  # => ["173", ["sortedset:14", "sortedset:78"]]

Parameters:

  • cursor (String, Integer)

    the cursor of the iteration

  • options (Hash)
    • :match => String: only return keys matching the pattern
    • :count => Integer: return count keys at most per iteration
    • :type => String: return keys only of the given type

Returns:

  • (String, Array<String>)

    the next cursor and all found keys



35
36
37
# File 'lib/valkey/commands/generic_commands.rb', line 35

def scan(cursor, **options)
  _scan(RequestType::SCAN, cursor, [], **options)
end

#scan_each(**options, &block) ⇒ Enumerator

Note:

Standalone mode only. Built on #scan, which has undefined routing behavior in cluster mode (see its note).

Scan the keyspace

Examples:

Retrieve all of the keys (with possible duplicates)

valkey.scan_each.to_a
  # => ["key:21", "key:47", "key:42"]

Execute block for each key matching a pattern

valkey.scan_each(:match => "key:1?") {|key| puts key}
  # => key:13
  # => key:18

Execute block for each key of a type

valkey.scan_each(:type => "hash") {|key| puts valkey.type(key)}
  # => "hash"
  # => "hash"

Parameters:

  • options (Hash)
    • :match => String: only return keys matching the pattern
    • :count => Integer: return count keys at most per iteration
    • :type => String: return keys only of the given type

Returns:

  • (Enumerator)

    an enumerator for all found keys



63
64
65
66
67
68
69
70
71
72
# File 'lib/valkey/commands/generic_commands.rb', line 63

def scan_each(**options, &block)
  return to_enum(:scan_each, **options) unless block_given?

  cursor = 0
  loop do
    cursor, keys = scan(cursor, **options)
    keys.each(&block)
    break if cursor == "0"
  end
end

#sort(key, by: nil, limit: nil, get: nil, order: nil, store: nil) ⇒ Array<String>, ...

Sort the elements in a list, set or sorted set.

Examples:

Retrieve the first 2 elements from an alphabetically sorted "list"

valkey.sort("list", :order => "alpha", :limit => [0, 2])
  # => ["a", "b"]

Store an alphabetically descending list in "target"

valkey.sort("list", :order => "desc alpha", :store => "target")
  # => 26

Parameters:

  • key (String)
  • options (Hash)
    • :by => String: use external key to sort elements by
    • :limit => [offset, count]: skip offset elements, return a maximum of count elements
    • :get => [String, Array<String>]: single key or array of keys to retrieve per element in the result
    • :order => String: combination of ASC, DESC and optionally ALPHA
    • :store => String: key to store the result at

Returns:

  • (Array<String>, Array<Array<String>>, Integer)
    • when :get is not specified, or holds a single element, an array of elements
    • when :get is specified, and holds more than one element, an array of elements where every element is an array with the result for every element specified in :get
    • when :store is specified, the number of elements in the stored result


445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
# File 'lib/valkey/commands/generic_commands.rb', line 445

def sort(key, by: nil, limit: nil, get: nil, order: nil, store: nil)
  args = [key]
  args << "BY" << by if by

  if limit
    args << "LIMIT"
    args.concat(limit)
  end

  get = Array(get)
  get.each do |item|
    args << "GET" << item
  end

  args.concat(order.split) if order
  args << "STORE" << store if store

  send_command(RequestType::SORT, args) do |reply|
    if get.size > 1 && !store
      reply.each_slice(get.size).to_a if reply
    else
      reply
    end
  end
end

#touch(*keys) ⇒ Object



471
472
473
# File 'lib/valkey/commands/generic_commands.rb', line 471

def touch(*keys)
  send_command(RequestType::TOUCH, keys.flatten)
end

#ttl(key) ⇒ Integer

Get the time to live (in seconds) for a key.

In valkey 2.6 or older the command returns -1 if the key does not exist or if the key exist but has no associated expire.

Starting with valkey 2.8 the return value in case of error changed:

- The command returns -2 if the key does not exist.
- The command returns -1 if the key exists but has no associated expire.

Parameters:

  • key (String)

Returns:

  • (Integer)

    remaining time to live in seconds.



142
143
144
# File 'lib/valkey/commands/generic_commands.rb', line 142

def ttl(key)
  send_command(RequestType::TTL, [key])
end

#type(key) ⇒ String

Determine the type stored at key.

Parameters:

  • key (String)

Returns:

  • (String)

    string, list, set, zset, hash or none



517
518
519
# File 'lib/valkey/commands/generic_commands.rb', line 517

def type(key)
  send_command(RequestType::TYPE, [key])
end

Unlink one or more keys.

Parameters:

  • keys (String, Array<String>)

Returns:

  • (Integer)

    number of keys that were unlinked



308
309
310
# File 'lib/valkey/commands/generic_commands.rb', line 308

def unlink(*keys)
  send_command(RequestType::UNLINK, keys.flatten)
end

#wait(numreplicas, timeout) ⇒ Integer

Block until all the previous write commands are successfully transferred and acknowledged by at least the specified number of replicas.

Examples:

Wait for 1 replica with 1 second timeout

valkey.wait(1, 1000)
  # => 1

Parameters:

  • numreplicas (Integer)

    minimum number of replicas to acknowledge

  • timeout (Integer)

    timeout in milliseconds (0 means block forever)

Returns:

  • (Integer)

    number of replicas that acknowledged

See Also:



487
488
489
# File 'lib/valkey/commands/generic_commands.rb', line 487

def wait(numreplicas, timeout)
  send_command(RequestType::WAIT, [numreplicas.to_s, timeout.to_s])
end

#waitaof(numlocal, numreplicas, timeout) ⇒ Array<Integer>

Block until all previous write commands are fsynced to the AOF of the local server and/or at least the specified number of replicas.

Examples:

Wait for local AOF fsync with no timeout

valkey.waitaof(1, 0, 0)
  # => [1, 0]

Wait for 1 replica fsync with 1 second timeout

valkey.waitaof(0, 1, 1000)
  # => [0, 0]

Parameters:

  • numlocal (Integer)

    number of local fsyncs required (0 or 1)

  • numreplicas (Integer)

    minimum number of replicas to fsync

  • timeout (Integer)

    timeout in milliseconds (0 means block forever)

Returns:

  • (Array<Integer>)

    array of two integers:

    • number of local servers (0 or 1) that fsynced
    • number of replicas that fsynced

See Also:



509
510
511
# File 'lib/valkey/commands/generic_commands.rb', line 509

def waitaof(numlocal, numreplicas, timeout)
  send_command(RequestType::WAIT_AOF, [numlocal.to_s, numreplicas.to_s, timeout.to_s])
end