website/docs/dev/custom-commands.md
Garnet supports registering custom commands and transactions implemented in C#, both programmatically on the server-side and through running dedicated REGISTERCS command in the client-side.
CustomRawStringFunctions base class (See example: main\GarnetServer\Extensions\DeleteIfMatch.cs)GarnetObjectBase base class, as well as a factory that creates your object type that inherits from the CustomObjectFactory base class (See example: main\GarnetServer\Extensions\MyDictObject.cs)CustomTransactionProcedure base class (See example: main\GarnetServer\Extensions\ReadWriteTxn.cs)CustomProcedure base class (See example: main\GarnetServer\Extensions\Sum.cs)To register a new custom command from the server-side, use the GarnetServer instance's RegisterApi, and call either NewCommand or NewTransactionProc according to the custom command type that you are trying to register.
CustomRawStringFunctions, call RegisterApi.NewCommand(string name, int numParams, CommandType type, CustomRawStringFunctions customFunctions, RespCommandsInfo commandInfo = null, long expirationTicks = 0), where customFunctions is an instance of the new concrete class.CustomObjectFactory, call RegisterApi.NewCommand(string name, int numParams, CommandType commandType, CustomObjectFactory factory, RespCommandsInfo commandInfo = null), where factory is an instance of the new concrete class.CustomTransactionProcedure, call NewTransactionProc(string name, int numParams, Func<CustomTransactionProcedure> proc, RespCommandsInfo commandInfo = null), where proc is a Func that returns an instance of the new concrete class.CustomProcedure, call RegisterApi.NewProcedure(string name, CustomProcedure customProcedure, RespCommandsInfo commandInfo = null, RespCommandDocs commandDocs = null), where customProcedure is an instance of the procedure concrete class.Note that each call to the RegisterApi has an optional RespCommandsInfo commandInfo parameter. This parameter allows you to supply Garnet with metadata regarding the custom command that will be visible to the client when running the COMMAND or COMMAND INFO commands.
To register a new custom command from the client-side, use the dedicated REGISTERCS command in the client app (note: this is an admin command).
The REGISTERCS command takes assemblies that exist on the server and contain implementations for either of the supported custom command classes, and registers the custom commands on the server according to parameters given by the client
The REGISTERCS command supports registering multiple commands and / or transactions from multiple files and / or directories containing C# binary files (*.dll / *.exe).
To enable registering client-side custom commands, you must specify a list of allowed paths from which assemblies can potentially be loaded, and enable module commands.
This is done by setting the configuration parameters EnableModuleCommand and ExtensionBinPaths.
Example (in garnet.config):
"EnableModuleCommand": "local",
"ExtensionBinPaths": ".\first\path\,..\..\second\path\"
Note #1: Assemblies can be loaded from any directory level under these specified paths
Note #2: By default, Garnet only allows loading of digitally signed assemblies. To remove that requirement (not recommended), set the configuration parameter ExtensionAllowOnlySignedAssemblies to false.
To run the REGISTERCS command, run the REGISTERCS keyword followed by one or more new command subcommands, followed by the optional INFO keyword which is followed by a path pointing to a JSON file containing a serialized array of RespCommandsInfo objects, containing command metadata (*.json), followed by the SRC keyword, which is followed by one or more paths to C# binary files or directories containing C# binary files (*.dll / *.exe).
REGISTERCS cmdType name numParams className [expTicks] [cmdType name numParams className [expTicks] ...] [INFO path] SRC path [path ...]
Each new command that you intend to register, is specified by either of the command type keywords, followed by its parameters.
cmdType name numParams cmdType className [expTicks]
Command Type:
The following keywords are legal values for cmdType:
Parameters:
name: Name of the new command
numParams: Number of parameters taken by the new command
className: Class name of concrete class implementing CustomRawStringFunctions or CustomObjectFactory for new READ / RMW commands, or CustomTransactionProcedure for new TXN commands (must exist in assemblies referenced in paths list)
expTicks: Command expiry in ticks (only relevant for custom raw string commands, ignored otherwise)
Note: If the server could not register one or more of the commands / transactions specified, or if it could not load or enumerate one or more of the files or directories specified in the REGISTERCS command, no action will be taken (i.e. no command will be registered), and the command execution will fail with an appropriate error message.
Returns +OK on success, otherwise --ERR message if any
ExtensionBinPaths in garnet.config)ExtensionBinPaths in garnet.config)ExtensionAllowOnlySignedAssemblies in garnet.conf)