Skip to main content
Loading

Record UDFs

This page describes how to create and use record user-defined functions (record UDFs) on a single record.

Overviewโ€‹

Record UDFs execute commands on a single record. A record UDF can create and update records based on a set of parameters. Background UDFs are record UDFs applied to the records returned from queries and secondary index queries.

See Typical uses for Record-Based UDFs.

Build and run a record UDFโ€‹

  1. Install and configure the Aerospike server.
  2. Write your UDF. UDFs are written in the Lua programming language. See the UDF Developer Guide.
  3. Register the UDF with the cluster.
  4. Invoke the UDF in your application.
  5. Execute the UDF on a record as a database Primary index query, or a set of records as a secondary index query.

Write record UDFsโ€‹

ops.lua

local function factorial_tail(i, acc)
if i == 0 then
return acc
end
return factorial_tail(i - 1, acc * i)
end

function factorial(rec, bin)
if aerospike:exists(rec) then
local v = rec[bin]
if type(v) == 'number' then
return factorial_tail(v, 1)
end
end
return nil
end
caution

To ease diagnosing test errors during the development process, develop UDFs using a single server node.

Register record UDFsโ€‹

UDFs must register with the Aerospike cluster before calling functions. UDFs only have to register with one node in the cluster.

The interactive aql CLI is a convenient way to register and execute UDFs.

aql> register module 'ops.lua'
OK, 1 module added.

Aerospike replicates registered UDFs through the entire cluster. Registered UDFs also persist on the node, so they persist through node and machine restarts.

note

Execute record UDFsโ€‹

Language-specific examples are available in the following Aerospike client libraries:

Execute record UDFs from aqlโ€‹

aql> INSERT INTO test.demo (PK, i) VALUES ('r1', 4)
OK, 1 record affected.

aql> EXECUTE ops.factorial('i') ON test.demo WHERE PK='r1'
+-----------+
| factorial |
+-----------+
| 24 |
+-----------+
1 row in set (0.000 secs)

aql> INSERT INTO test.demo (PK, i) VALUES ('r2', 9)
OK, 1 record affected.

aql> EXECUTE ops.factorial('i') ON test.demo WHERE PK='r2'
+-----------+
| factorial |
+-----------+
| 362880 |
+-----------+
1 row in set (0.001 secs)

aql> INSERT INTO test.demo (PK, i) VALUES ('r3', 0)
OK, 1 record affected.

aql> EXECUTE ops.factorial('i') ON test.demo WHERE PK='r3'
+-----------+
| factorial |
+-----------+
| 1 |
+-----------+
1 row in set (0.001 secs)

aql> INSERT INTO test.demo (PK, i) VALUES ('r4', 'llama')
OK, 1 record affected.

aql> EXECUTE ops.factorial('i') ON test.demo WHERE PK='r4'
+-----------+
| factorial |
+-----------+
| |
+-----------+
1 row in set (0.000 secs)

Examplesโ€‹

Known limitationsโ€‹

  • The Aerospike Record UDF system supports only single return values.

    Although Lua allows multiple values to return as function result values, the final UDF returning to the client application can only contain a single object as the return value. Use lists to return multiple objects.

  • The Aerospike record UDF system does not allow multi-record operations.

    For example, you can use UDFs that on writes to a particular key, also updates other keys. A UDF can also request values from other keys to simulate joins. In Aerospike, keys can be on other servers, so these functions require asynchronous operations, which can cause deadlocks.

  • Aerospike only supports limited sandboxing to protect the system from crashes.

    Aerospike provides time limits to terminate individual UDF invocations running longer than the set time. However, it is still possible (especially by calling a C module from Lua or very high memory usage) to crash the entire server.

  • Aerospike does not support record UDF on batch results.

  • A record UDF command inside a transaction will lock the record (blocking others from writing to it with an AS_ERR_MRT_BLOCKED error code 120) regardless of whether it performs read or write operations.

Referencesโ€‹