From 170f48574d5145797c90fb6072c1a063fab8d063 Mon Sep 17 00:00:00 2001 From: Tal Zaccai Date: Tue, 18 Feb 2025 16:02:39 -0800 Subject: [PATCH] Adding HCOLLECT info & docs to GarnetCommandsInfo/Docs.json (#1020) * Adding HCOLLECT info & docs to GarnetCommandDocs/Info & updating RespCommandDocs/Info * Adding SPUBLISH, SSUBSCRIBE TO GarnetCommandsInfo.json --- libs/resources/RespCommandsDocs.json | 179 ++++++++++------ libs/resources/RespCommandsInfo.json | 195 +++++++++--------- .../CommandInfoUpdater/CommandInfoUpdater.cs | 2 +- .../GarnetCommandsDocs.json | 6 + .../GarnetCommandsInfo.json | 75 +++++++ test/Garnet.test/RespCommandTests.cs | 3 +- 6 files changed, 304 insertions(+), 156 deletions(-) diff --git a/libs/resources/RespCommandsDocs.json b/libs/resources/RespCommandsDocs.json index 15cc917695..9e217fb06f 100644 --- a/libs/resources/RespCommandsDocs.json +++ b/libs/resources/RespCommandsDocs.json @@ -1027,6 +1027,14 @@ "Token": "NO" } ] + }, + { + "TypeDiscriminator": "RespCommandBasicArgument", + "Name": "MAXAGE", + "DisplayText": "maxage", + "Type": "Integer", + "Token": "MAXAGE", + "ArgumentFlags": "Optional" } ] } @@ -1175,7 +1183,7 @@ { "Command": "CLUSTER", "Name": "CLUSTER", - "Summary": "A container for Redis Cluster commands.", + "Summary": "A container for Redis Cluster internal commands.", "Group": "Cluster", "Complexity": "Depends on subcommand.", "SubCommands": [ @@ -1429,6 +1437,13 @@ "Group": "Cluster", "Complexity": "O(N) where N is the total number of Cluster nodes" }, + { + "Command": "CLUSTER_PUBLISH", + "Name": "CLUSTER|PUBLISH", + "Summary": "Processes a forwarded published message from any node in the cluster", + "Group": "Cluster", + "Complexity": "O(1)" + }, { "Command": "CLUSTER_REPLICAS", "Name": "CLUSTER|REPLICAS", @@ -1570,6 +1585,13 @@ "Complexity": "O(N) where N is the total number of Cluster nodes", "DocFlags": "Deprecated", "ReplacedBy": "\u0060CLUSTER SHARDS\u0060" + }, + { + "Command": "CLUSTER_SPUBLISH", + "Name": "CLUSTER|SPUBLISH", + "Summary": "Processes a forwarded published message from a node in the same shard", + "Group": "Cluster", + "Complexity": "O(1)" } ] }, @@ -1603,22 +1625,6 @@ } ] }, - { - "Command": "COMMAND_INFO", - "Name": "COMMAND|INFO", - "Summary": "Returns information about one, multiple or all commands.", - "Group": "Server", - "Complexity": "O(N) where N is the number of commands to look up", - "Arguments": [ - { - "TypeDiscriminator": "RespCommandBasicArgument", - "Name": "COMMAND-NAME", - "DisplayText": "command-name", - "Type": "String", - "ArgumentFlags": "Optional, Multiple" - } - ] - }, { "Command": "COMMAND_GETKEYS", "Name": "COMMAND|GETKEYS", @@ -1662,6 +1668,22 @@ "ArgumentFlags": "Optional, Multiple" } ] + }, + { + "Command": "COMMAND_INFO", + "Name": "COMMAND|INFO", + "Summary": "Returns information about one, multiple or all commands.", + "Group": "Server", + "Complexity": "O(N) where N is the number of commands to look up", + "Arguments": [ + { + "TypeDiscriminator": "RespCommandBasicArgument", + "Name": "COMMAND-NAME", + "DisplayText": "command-name", + "Type": "String", + "ArgumentFlags": "Optional, Multiple" + } + ] } ] }, @@ -1780,9 +1802,10 @@ { "Command": "DEBUG", "Name": "DEBUG", - "Summary": "Depends on subcommand.", + "Summary": "A container for debugging commands.", "Group": "Server", - "Complexity": "O(1)" + "Complexity": "Depends on subcommand.", + "DocFlags": "SysCmd" }, { "Command": "DECR", @@ -3890,6 +3913,14 @@ "Type": "Integer", "Token": "COUNT", "ArgumentFlags": "Optional" + }, + { + "TypeDiscriminator": "RespCommandBasicArgument", + "Name": "NOVALUES", + "DisplayText": "novalues", + "Type": "PureToken", + "Token": "NOVALUES", + "ArgumentFlags": "Optional" } ] }, @@ -5419,7 +5450,7 @@ "Name": "NUMPARAMS", "DisplayText": "numParams", "Type": "Integer", - "Summary": "Number of parameters of the command to register" + "Summary": "Numer of parameters of the command to register" }, { "TypeDiscriminator": "RespCommandBasicArgument", @@ -5615,12 +5646,51 @@ }, { "TypeDiscriminator": "RespCommandBasicArgument", - "Name": "SERIALIZEDVALUE", + "Name": "SERIALIZED-VALUE", "DisplayText": "serialized-value", "Type": "String" + }, + { + "TypeDiscriminator": "RespCommandBasicArgument", + "Name": "REPLACE", + "DisplayText": "replace", + "Type": "PureToken", + "Token": "REPLACE", + "ArgumentFlags": "Optional" + }, + { + "TypeDiscriminator": "RespCommandBasicArgument", + "Name": "ABSTTL", + "DisplayText": "absttl", + "Type": "PureToken", + "Token": "ABSTTL", + "ArgumentFlags": "Optional" + }, + { + "TypeDiscriminator": "RespCommandBasicArgument", + "Name": "SECONDS", + "DisplayText": "seconds", + "Type": "Integer", + "Token": "IDLETIME", + "ArgumentFlags": "Optional" + }, + { + "TypeDiscriminator": "RespCommandBasicArgument", + "Name": "FREQUENCY", + "DisplayText": "frequency", + "Type": "Integer", + "Token": "FREQ", + "ArgumentFlags": "Optional" } ] }, + { + "Command": "ROLE", + "Name": "ROLE", + "Summary": "Returns the replication role.", + "Group": "Server", + "Complexity": "O(1)" + }, { "Command": "RPOP", "Name": "RPOP", @@ -6558,6 +6628,27 @@ } ] }, + { + "Command": "SPUBLISH", + "Name": "SPUBLISH", + "Summary": "Post a message to a shard channel", + "Group": "PubSub", + "Complexity": "O(N) where N is the number of clients subscribed to the receiving shard channel.", + "Arguments": [ + { + "TypeDiscriminator": "RespCommandBasicArgument", + "Name": "SHARDCHANNEL", + "DisplayText": "shardchannel", + "Type": "String" + }, + { + "TypeDiscriminator": "RespCommandBasicArgument", + "Name": "MESSAGE", + "DisplayText": "message", + "Type": "String" + } + ] + }, { "Command": "SRANDMEMBER", "Name": "SRANDMEMBER", @@ -6643,23 +6734,18 @@ ] }, { - "Command": "SPUBLISH", - "Name": "SPUBLISH", - "Summary": "Posts a message to a shard channel.", + "Command": "SSUBSCRIBE", + "Name": "SSUBSCRIBE", + "Summary": "Listens for messages published to shard channels.", "Group": "PubSub", - "Complexity": "O(N) where N is the number of clients subscribed to the receiving shard channel.", + "Complexity": "O(N) where N is the number of shard channels to subscribe to.", "Arguments": [ { "TypeDiscriminator": "RespCommandBasicArgument", "Name": "SHARDCHANNEL", "DisplayText": "shardchannel", - "Type": "String" - }, - { - "TypeDiscriminator": "RespCommandBasicArgument", - "Name": "MESSAGE", - "DisplayText": "message", - "Type": "String" + "Type": "String", + "ArgumentFlags": "Multiple" } ] }, @@ -6695,22 +6781,6 @@ } ] }, - { - "Command": "SSUBSCRIBE", - "Name": "SSUBSCRIBE", - "Summary": "Listens for messages published to shard channels.", - "Group": "PubSub", - "Complexity": "O(N) where N is the number of shard channels to subscribe to.", - "Arguments": [ - { - "TypeDiscriminator": "RespCommandBasicArgument", - "Name": "shardchannel", - "DisplayText": "channel", - "Type": "String", - "ArgumentFlags": "Multiple" - } - ] - }, { "Command": "SUBSTR", "Name": "SUBSTR", @@ -6821,13 +6891,6 @@ } ] }, - { - "Command": "ROLE", - "Name": "ROLE", - "Summary": "Returns the replication role.", - "Group": "Server", - "Complexity": "O(1)" - }, { "Command": "UNLINK", "Name": "UNLINK", @@ -7593,7 +7656,7 @@ { "Command": "ZRANGEBYLEX", "Name": "ZRANGEBYLEX", - "Summary": "Returns the number of members in a sorted set within a lexicographical range.", + "Summary": "Returns members in a sorted set within a lexicographical range.", "Group": "SortedSet", "Complexity": "O(log(N)\u002BM) with N being the number of elements in the sorted set and M the number of elements being returned. If M is constant (e.g. always asking for the first 10 elements with LIMIT), you can consider it O(log(N)).", "DocFlags": "Deprecated", @@ -7610,13 +7673,13 @@ "TypeDiscriminator": "RespCommandBasicArgument", "Name": "MIN", "DisplayText": "min", - "Type": "Double" + "Type": "String" }, { "TypeDiscriminator": "RespCommandBasicArgument", "Name": "MAX", "DisplayText": "max", - "Type": "Double" + "Type": "String" }, { "TypeDiscriminator": "RespCommandContainerArgument", diff --git a/libs/resources/RespCommandsInfo.json b/libs/resources/RespCommandsInfo.json index 2d84a2c6ce..d74adfda93 100644 --- a/libs/resources/RespCommandsInfo.json +++ b/libs/resources/RespCommandsInfo.json @@ -617,43 +617,6 @@ "Flags": "Admin, NoMulti, NoScript", "AclCategories": "Admin, Dangerous, Slow, Garnet" }, - { - "Command": "CLUSTER_PUBLISH", - "Name": "CLUSTER|PUBLISH", - "IsInternal": true, - "Arity": 4, - "Flags": "Loading, NoScript, PubSub, Stale", - "FirstKey": 1, - "LastKey": 1, - "Step": 1, - "AclCategories": "Admin, PubSub, Slow, Garnet" - }, - { - "Command": "CLUSTER_SPUBLISH", - "Name": "CLUSTER|SPUBLISH", - "IsInternal": true, - "Arity": 4, - "Flags": "Loading, NoScript, PubSub, Stale", - "FirstKey": 1, - "LastKey": 1, - "Step": 1, - "AclCategories": "Admin, PubSub, Slow, Garnet", - "KeySpecifications": [ - { - "BeginSearch": { - "TypeDiscriminator": "BeginSearchIndex", - "Index": 1 - }, - "FindKeys": { - "TypeDiscriminator": "FindKeysRange", - "LastKey": 0, - "KeyStep": 1, - "Limit": 0 - }, - "Flags": "RO" - } - ] - }, { "Command": "CLUSTER_BUMPEPOCH", "Name": "CLUSTER|BUMPEPOCH", @@ -837,6 +800,17 @@ "nondeterministic_output" ] }, + { + "Command": "CLUSTER_PUBLISH", + "Name": "CLUSTER|PUBLISH", + "IsInternal": true, + "Arity": 4, + "Flags": "Loading, NoScript, PubSub, Stale", + "FirstKey": 1, + "LastKey": 1, + "Step": 1, + "AclCategories": "Admin, PubSub, Slow, Garnet" + }, { "Command": "CLUSTER_REPLICAS", "Name": "CLUSTER|REPLICAS", @@ -926,6 +900,32 @@ "Arity": 1, "Flags": "Admin, NoMulti, NoScript", "AclCategories": "Admin, Dangerous, Slow, Garnet" + }, + { + "Command": "CLUSTER_SPUBLISH", + "Name": "CLUSTER|SPUBLISH", + "IsInternal": true, + "Arity": 4, + "Flags": "Loading, NoScript, PubSub, Stale", + "FirstKey": 1, + "LastKey": 1, + "Step": 1, + "AclCategories": "Admin, PubSub, Slow, Garnet", + "KeySpecifications": [ + { + "BeginSearch": { + "TypeDiscriminator": "BeginSearchIndex", + "Index": 1 + }, + "FindKeys": { + "TypeDiscriminator": "FindKeysRange", + "LastKey": 0, + "KeyStep": 1, + "Limit": 0 + }, + "Flags": "RO" + } + ] } ] }, @@ -956,16 +956,6 @@ "nondeterministic_output_order" ] }, - { - "Command": "COMMAND_INFO", - "Name": "COMMAND|INFO", - "Arity": -2, - "Flags": "Loading, Stale", - "AclCategories": "Connection, Slow", - "Tips": [ - "nondeterministic_output_order" - ] - }, { "Command": "COMMAND_GETKEYS", "Name": "COMMAND|GETKEYS", @@ -979,6 +969,16 @@ "Arity": -3, "Flags": "Loading, Stale", "AclCategories": "Connection, Slow" + }, + { + "Command": "COMMAND_INFO", + "Name": "COMMAND|INFO", + "Arity": -2, + "Flags": "Loading, Stale", + "AclCategories": "Connection, Slow", + "Tips": [ + "nondeterministic_output_order" + ] } ] }, @@ -1082,7 +1082,7 @@ "Command": "DEBUG", "Name": "DEBUG", "Arity": -2, - "Flags": "Admin, Noscript, Loading, Stale", + "Flags": "Admin, Loading, NoScript, Stale", "AclCategories": "Admin, Dangerous, Slow" }, { @@ -1179,7 +1179,10 @@ "FirstKey": 1, "LastKey": 1, "Step": 1, - "AclCategories": "KeySpace, Read", + "AclCategories": "KeySpace, Read, Slow", + "Tips": [ + "nondeterministic_output" + ], "KeySpecifications": [ { "BeginSearch": { @@ -3569,13 +3572,20 @@ "FindKeys": { "TypeDiscriminator": "FindKeysRange", "LastKey": 0, - "KeyStep": 0, + "KeyStep": 1, "Limit": 0 }, "Flags": "OW, Update" } ] }, + { + "Command": "ROLE", + "Name": "ROLE", + "Arity": 1, + "Flags": "Fast, Loading, NoScript, Stale", + "AclCategories": "Admin, Dangerous, Fast" + }, { "Command": "RPOP", "Name": "RPOP", @@ -4110,7 +4120,7 @@ "KeyStep": 1, "Limit": 0 }, - "Flags": "RW, Update" + "Flags": "OW, Update" }, { "BeginSearch": { @@ -4327,6 +4337,31 @@ } ] }, + { + "Command": "SPUBLISH", + "Name": "SPUBLISH", + "Arity": 3, + "Flags": "Loading, NoScript, PubSub, Stale", + "FirstKey": 1, + "LastKey": 1, + "Step": 1, + "AclCategories": "PubSub, Read, Slow", + "KeySpecifications": [ + { + "BeginSearch": { + "TypeDiscriminator": "BeginSearchIndex", + "Index": 1 + }, + "FindKeys": { + "TypeDiscriminator": "FindKeysRange", + "LastKey": 0, + "KeyStep": 1, + "Limit": 0 + }, + "Flags": "RO" + } + ] + }, { "Command": "SRANDMEMBER", "Name": "SRANDMEMBER", @@ -4408,38 +4443,6 @@ } ] }, - { - "Command": "STRLEN", - "Name": "STRLEN", - "Arity": 2, - "Flags": "Fast, ReadOnly", - "FirstKey": 1, - "LastKey": 1, - "Step": 1, - "AclCategories": "Fast, Read, String", - "KeySpecifications": [ - { - "BeginSearch": { - "TypeDiscriminator": "BeginSearchIndex", - "Index": 1 - }, - "FindKeys": { - "TypeDiscriminator": "FindKeysRange", - "LastKey": 0, - "KeyStep": 1, - "Limit": 0 - }, - "Flags": "RO" - } - ] - }, - { - "Command": "SUBSCRIBE", - "Name": "SUBSCRIBE", - "Arity": -2, - "Flags": "Loading, NoScript, PubSub, Stale", - "AclCategories": "PubSub, Slow" - }, { "Command": "SSUBSCRIBE", "Name": "SSUBSCRIBE", @@ -4448,7 +4451,7 @@ "FirstKey": 1, "LastKey": -1, "Step": 1, - "AclCategories": "PubSub, Slow, Read", + "AclCategories": "PubSub, Read, Slow", "KeySpecifications": [ { "BeginSearch": { @@ -4466,14 +4469,14 @@ ] }, { - "Command": "SPUBLISH", - "Name": "SPUBLISH", - "Arity": 3, - "Flags": "Loading, NoScript, PubSub, Stale", + "Command": "STRLEN", + "Name": "STRLEN", + "Arity": 2, + "Flags": "Fast, ReadOnly", "FirstKey": 1, "LastKey": 1, "Step": 1, - "AclCategories": "PubSub, Slow, Read", + "AclCategories": "Fast, Read, String", "KeySpecifications": [ { "BeginSearch": { @@ -4490,6 +4493,13 @@ } ] }, + { + "Command": "SUBSCRIBE", + "Name": "SUBSCRIBE", + "Arity": -2, + "Flags": "Loading, NoScript, PubSub, Stale", + "AclCategories": "PubSub, Slow" + }, { "Command": "SUBSTR", "Name": "SUBSTR", @@ -4644,13 +4654,6 @@ } ] }, - { - "Command": "ROLE", - "Name": "ROLE", - "Arity": 1, - "Flags": "NoScript, Loading, Stale, Fast", - "AclCategories": "Admin, Fast, Dangerous" - }, { "Command": "UNLINK", "Name": "UNLINK", diff --git a/playground/CommandInfoUpdater/CommandInfoUpdater.cs b/playground/CommandInfoUpdater/CommandInfoUpdater.cs index ad1901c14a..fd0ab4238e 100644 --- a/playground/CommandInfoUpdater/CommandInfoUpdater.cs +++ b/playground/CommandInfoUpdater/CommandInfoUpdater.cs @@ -15,7 +15,7 @@ namespace CommandInfoUpdater /// public class CommandInfoUpdater { - const int QUERY_CMD_BATCH_SIZE = 25; + const int QUERY_CMD_BATCH_SIZE = 10; private static readonly string CommandInfoFileName = "RespCommandsInfo.json"; private static readonly string GarnetCommandInfoJsonPath = "GarnetCommandsInfo.json"; diff --git a/playground/CommandInfoUpdater/GarnetCommandsDocs.json b/playground/CommandInfoUpdater/GarnetCommandsDocs.json index 84c80cea0e..bf0bd62dc9 100644 --- a/playground/CommandInfoUpdater/GarnetCommandsDocs.json +++ b/playground/CommandInfoUpdater/GarnetCommandsDocs.json @@ -186,6 +186,12 @@ "Summary": "Forces garbage collection.", "Group": "Server" }, + { + "Command": "HCOLLECT", + "Name": "HCOLLECT", + "Summary": "Manually trigger deletion of expired fields from memory", + "Group": "Hash" + }, { "Command": "SECONDARYOF", "Name": "SECONDARYOF", diff --git a/playground/CommandInfoUpdater/GarnetCommandsInfo.json b/playground/CommandInfoUpdater/GarnetCommandsInfo.json index 04570affc7..1cc3b765dd 100644 --- a/playground/CommandInfoUpdater/GarnetCommandsInfo.json +++ b/playground/CommandInfoUpdater/GarnetCommandsInfo.json @@ -393,6 +393,31 @@ "KeySpecifications": null, "SubCommands": null }, + { + "Command": "HCOLLECT", + "Name": "HCOLLECT", + "Arity": 2, + "Flags": "Admin, Write", + "FirstKey": 1, + "LastKey": 1, + "Step": 1, + "AclCategories": "Admin, Hash, Write, Garnet", + "KeySpecifications": [ + { + "BeginSearch": { + "TypeDiscriminator": "BeginSearchIndex", + "Index": 1 + }, + "FindKeys": { + "TypeDiscriminator": "FindKeysRange", + "LastKey": 0, + "KeyStep": 1, + "Limit": 0 + }, + "Flags": "RW, Access, Update" + } + ] + }, { "Command": "LATENCY", "Name": "LATENCY", @@ -730,6 +755,56 @@ } ] }, + { + "Command": "SPUBLISH", + "Name": "SPUBLISH", + "Arity": 3, + "Flags": "Loading, NoScript, PubSub, Stale", + "FirstKey": 1, + "LastKey": 1, + "Step": 1, + "AclCategories": "PubSub, Slow, Read", + "KeySpecifications": [ + { + "BeginSearch": { + "TypeDiscriminator": "BeginSearchIndex", + "Index": 1 + }, + "FindKeys": { + "TypeDiscriminator": "FindKeysRange", + "LastKey": 0, + "KeyStep": 1, + "Limit": 0 + }, + "Flags": "RO" + } + ] + }, + { + "Command": "SSUBSCRIBE", + "Name": "SSUBSCRIBE", + "Arity": -2, + "Flags": "Loading, NoScript, PubSub, Stale", + "FirstKey": 1, + "LastKey": -1, + "Step": 1, + "AclCategories": "PubSub, Slow, Read", + "KeySpecifications": [ + { + "BeginSearch": { + "TypeDiscriminator": "BeginSearchIndex", + "Index": 1 + }, + "FindKeys": { + "TypeDiscriminator": "FindKeysRange", + "LastKey": -1, + "KeyStep": 1, + "Limit": 0 + }, + "Flags": "RO" + } + ] + }, { "Command": "WATCH", "Name": "WATCH", diff --git a/test/Garnet.test/RespCommandTests.cs b/test/Garnet.test/RespCommandTests.cs index c5cc6f713e..757286fd6d 100644 --- a/test/Garnet.test/RespCommandTests.cs +++ b/test/Garnet.test/RespCommandTests.cs @@ -137,7 +137,8 @@ public void CommandsDocsCoverageTest() } var allCommands = Enum.GetValues().Except(noMetadataCommands).Except(internalOnlyCommands); - CollectionAssert.AreEquivalent(allCommands, commandsWithDocs, "Some commands have missing docs. Please see https://microsoft.github.io/garnet/docs/dev/garnet-api#adding-command-info for more details."); + Assert.That(commandsWithDocs, Is.SupersetOf(allCommands), + "Some commands have missing docs. Please see https://microsoft.github.io/garnet/docs/dev/garnet-api#adding-command-info for more details."); } ///