Skip to content

Ask the HotKV docs

Answers come only from these docs and can be wrong; check the linked pages before you rely on them.

Functions

Last updated

Functions are server-side Lua code with names. Instead of sending a script and tracking its SHA1 digest, you load a library once and then call its functions by name, like commands. Libraries are part of the data set: they are saved with snapshots, written to the append-only file, and sent to replicas.

Functions run in the same Lua environment as scripts, with the same libraries, sandbox rules, atomicity and time limits.

A library is Lua code whose first line is #!lua name=<library>. When it is loaded, its top-level code runs once and registers its functions with redis.register_function(). Each function receives two tables, the keys and the other arguments.

#!lua name=inventory
local function take(keys, args)
local stock = tonumber(redis.call('GET', keys[1]) or '0')
local wanted = tonumber(args[1])
if stock < wanted then
return redis.error_reply('insufficient stock')
end
return redis.call('DECRBY', keys[1], wanted)
end
local function level(keys, args)
return redis.call('GET', keys[1])
end
redis.register_function('take', take)
redis.register_function{
function_name = 'level',
callback = level,
flags = { 'no-writes' },
description = 'Current stock for one item',
}

The table form of register_function takes function_name, callback, and optionally flags and description. Library names may contain letters, digits and underscores. The function flags are the same as for scripts: no-writes, allow-oom, allow-stale, no-cluster and allow-cross-slot-keys (see Lua scripting).

FUNCTION LOAD takes the library code and replies with the library name. With redis-cli, -x reads the last argument from standard input, which is the easiest way to send a file:

Terminal window
redis-cli -x FUNCTION LOAD < inventory.lua
"inventory"

Loading a library whose name already exists fails with ERR Library 'inventory' already exists; pass REPLACE to update it:

Terminal window
redis-cli -x FUNCTION LOAD REPLACE < inventory.lua

FCALL calls a function with the number of keys, the keys, and the arguments, just like EVAL. FCALL_RO calls a function registered with no-writes, and can run on a read-only replica.

127.0.0.1:6379> SET stock:widget 10
OK
127.0.0.1:6379> FCALL take 1 stock:widget 3
(integer) 7
127.0.0.1:6379> FCALL take 1 stock:widget 30
(error) insufficient stock
127.0.0.1:6379> FCALL_RO level 1 stock:widget
"7"
127.0.0.1:6379> FCALL missing 0
(error) ERR Function not found
Command What it does
FUNCTION LIST [LIBRARYNAME pattern] [WITHCODE] Each library with its engine, functions, descriptions and flags
FUNCTION DELETE library Remove a library and its functions
FUNCTION FLUSH [ASYNC | SYNC] Remove every library
FUNCTION DUMP Every library as one payload, for backup
FUNCTION RESTORE payload [FLUSH | APPEND | REPLACE] Load a FUNCTION DUMP payload
FUNCTION STATS Number of libraries and functions
FUNCTION KILL Stop a function that is running too long
127.0.0.1:6379> FUNCTION LIST
1) 1) "library_name"
2) "inventory"
3) "engine"
4) "LUA"
5) "functions"
6) 1) 1) "name"
2) "take"
3) "description"
4) (nil)
5) "flags"
6) (empty array)
2) 1) "name"
2) "level"
3) "description"
4) "Current stock for one item"
5) "flags"
6) 1) no-writes

FUNCTION RESTORE appends by default and fails if a library in the payload already exists. REPLACE overwrites libraries of the same name, and FLUSH removes every library first.

A function that runs longer than busy-reply-threshold (5000 ms by default) makes other clients’ waiting commands reply BUSY, as a script does. FUNCTION KILL stops it if it has not written anything yet; otherwise it replies UNKILLABLE. See Lua scripting.

While FUNCTION LOAD runs a library’s top-level code, that code may only register functions; it cannot call commands, and it is stopped if it runs for more than half a second.

  • Libraries are saved in snapshots and restored when the server starts.
  • FUNCTION LOAD, DELETE, FLUSH and RESTORE are written to the append-only file and sent to replicas, so replicas always have the primary’s libraries. A replica refuses them from its own clients.
  • In a cluster, each shard has its own libraries. Load a library on every primary, for example with redis-cli --cluster call <host:port> FUNCTION LOAD .... See What cannot be clustered.

Library syntax, FCALL, FCALL_RO and the FUNCTION subcommands behave as in Redis 7. The difference is the FUNCTION DUMP payload format, which is specific to HotKV.