mirror of
https://github.com/EchoVault/SugarDB.git
synced 2025-09-26 20:11:15 +08:00
158 lines
6.2 KiB
Lua
158 lines
6.2 KiB
Lua
|
|
-- The keyword to trigger the command
|
|
command = "LUA.ZSET"
|
|
|
|
--[[
|
|
The string array of categories this command belongs to.
|
|
This array can contain both built-in categories and new custom categories.
|
|
]]
|
|
categories = {"sortedset", "write", "fast"}
|
|
|
|
-- The description of the command
|
|
description = "(LUA.ZSET key member score [member score ...]) \
|
|
This is an example of working with sorted sets in lua scripts"
|
|
|
|
-- Whether the command should be synced across the RAFT cluster
|
|
sync = true
|
|
|
|
--[[
|
|
keyExtractionFunc is a function that extracts the keys from the command and returns them to SugarDB.keyExtractionFunc
|
|
The returned data from this function is used in the Access Control Layer to determine if the current connection is
|
|
authorized to execute this command. The function must return a table that specifies which keys in this command
|
|
are read keys and which ones are write keys.
|
|
Example return: {["readKeys"] = {"key1", "key2"}, ["writeKeys"] = {"key3", "key4", "key5"}}
|
|
|
|
1. "command" is a string array representing the command that triggered this key extraction function.
|
|
|
|
2. "args" is a string array of the modifier args that were passed when loading the module into SugarDB.
|
|
These args are passed to the key extraction function everytime it's invoked.
|
|
]]
|
|
function keyExtractionFunc (command, args)
|
|
for k,v in pairs(args) do
|
|
print(k, v)
|
|
end
|
|
if (#command ~= 4) then
|
|
error("wrong number of args, expected 2")
|
|
end
|
|
return { ["readKeys"] = {}, ["writeKeys"] = {command[2], command[3], command[4]} }
|
|
end
|
|
|
|
--[[
|
|
handlerFunc is the command's handler function. The function is passed some arguments that allow it to interact with
|
|
SugarDB. The function must return a valid RESP response or throw an error.
|
|
The handler function accepts the following args:
|
|
|
|
1. "context" is a table that contains some information about the environment this command has been executed in.
|
|
Example: {["protocol"] = 2, ["database"] = 0}
|
|
This object contains the following properties:
|
|
i) protocol - the protocol version of the client that executed the command (either 2 or 3).
|
|
ii) database - the active database index of the client that executed the command.
|
|
|
|
2. "command" is the string array representing the command that triggered this handler function.
|
|
|
|
3. "keyExists" is a function that can be called to check if a list of keys exists in the SugarDB store database.
|
|
This function accepts a string array of keys to check and returns a table with each key having a corresponding
|
|
boolean value indicating whether it exists.
|
|
Examples:
|
|
i) Example invocation: keyExists({"key1", "key2", "key3"})
|
|
ii) Example return: {["key1"] = true, ["key2"] = false, ["key3"] = true}
|
|
|
|
4. "getValues" is a function that can be called to retrieve values from the SugarDB store database.
|
|
The function accepts a string array of keys whose values we would like to fetch, and returns a table with each key
|
|
containing the corresponding value from the store.
|
|
The possible data types for the values are: number, string, nil, hash, set, zset
|
|
Examples:
|
|
i) Example invocation: getValues({"key1", "key2", "key3"})
|
|
ii) Example return: {["key1"] = 3.142, ["key2"] = nil, ["key3"] = "Pi"}
|
|
|
|
5. "setValues" is a function that can be called to set values in the active database in the SugarDB store.
|
|
This function accepts a table with keys and the corresponding values to set for each key in the active database
|
|
in the store.
|
|
The accepted data types for the values are: number, string, nil, hash, set, zset.
|
|
The setValues function does not return anything.
|
|
Examples:
|
|
i) Example invocation: setValues({["key1"] = 3.142, ["key2"] = nil, ["key3"] = "Pi"})
|
|
|
|
6. "args" is a string array of the modifier args passed to the module at load time. These args are passed to the
|
|
handler everytime it's invoked.
|
|
]]
|
|
function handlerFunc(ctx, command, keyExists, getValues, setValues, args)
|
|
-- Ensure there are enough arguments
|
|
if #command < 4 then
|
|
error("wrong number of arguments, expected at least 3")
|
|
end
|
|
|
|
local key1 = command[2]
|
|
local key2 = command[3]
|
|
local key3 = command[4]
|
|
|
|
-- Create `zmember` instances
|
|
local member1 = zmember.new({value = "member1", score = 10})
|
|
local member2 = zmember.new({value = "member2", score = 20})
|
|
local member3 = zmember.new({value = "member3", score = 30})
|
|
|
|
-- Create a `zset` and add initial members
|
|
local zset1 = zset.new({member1, member2})
|
|
|
|
-- Test `add` method with a new member
|
|
zset1:add({member3})
|
|
|
|
-- Test `update` method by modifying an existing member
|
|
zset1:update({zmember.new({value = "member1", score = 15})})
|
|
|
|
-- Test `remove` method
|
|
zset1:remove("member2")
|
|
|
|
-- Test `cardinality` method
|
|
local zset1Cardinality = zset1:cardinality()
|
|
|
|
-- Test `contains` method
|
|
local containsMember3 = zset1:contains("member3")
|
|
local containsNonExistent = zset1:contains("nonexistent")
|
|
|
|
-- Test `random` method
|
|
local randomMembers = zset1:random(2)
|
|
|
|
-- Test `all` method
|
|
local allMembers = zset1:all()
|
|
|
|
-- Create another `zset` to test `subtract`
|
|
local zset2 = zset.new({zmember.new({value = "member3", score = 30})})
|
|
local zsetSubtracted = zset1:subtract({zset2})
|
|
|
|
-- Store the `zset` objects in SugarDB
|
|
setValues({
|
|
[key1] = zset1,
|
|
[key2] = zset2,
|
|
[key3] = zsetSubtracted
|
|
})
|
|
|
|
-- Retrieve the stored `zset` objects to verify storage
|
|
local storedValues = getValues({key1, key2, key3})
|
|
local storedZset1 = storedValues[key1]
|
|
local storedZset2 = storedValues[key2]
|
|
local storedSubtractedZset = storedValues[key3]
|
|
|
|
-- Perform consistency checks
|
|
if not storedZset1 or storedZset1:cardinality() ~= zset1:cardinality() then
|
|
error("Stored zset1 does not match the modified zset1")
|
|
end
|
|
if not storedZset2 or storedZset2:cardinality() ~= zset2:cardinality() then
|
|
error("Stored zset2 does not match the modified zset2")
|
|
end
|
|
if not storedSubtractedZset or storedSubtractedZset:cardinality() ~= zsetSubtracted:cardinality() then
|
|
error("Stored subtracted zset does not match the computed result")
|
|
end
|
|
|
|
-- Test `zmember` methods
|
|
local memberValue = member1:value()
|
|
member1:value("updated_member1")
|
|
local updatedValue = member1:value()
|
|
|
|
local memberScore = member1:score()
|
|
member1:score(50)
|
|
local updatedScore = member1:score()
|
|
|
|
-- Return an "OK" response
|
|
return "+OK\r\n"
|
|
end |