feat(introspection): add tableNames and names to catalog
This commit is contained in:
1 parent
bba0243a39
commit
eb1528087c
1 file changed
+106
@@ -151,3 +151,109 @@ defmodule Excache.Command.Introspection.Catalog do
|
||||
"UNWATCH" => {1, [:noscript, :loading, :stale, :fast], 0, 0, 0, :transactions}
|
||||
}
|
||||
|
||||
@keyRules %{
|
||||
"XREAD" => :streams,
|
||||
"XREADGROUP" => :streams,
|
||||
"SINTERCARD" => {:numkeys, 1},
|
||||
"BLMPOP" => {:numkeys, 2},
|
||||
"OBJECT" => {:subcommand, ~w(ENCODING REFCOUNT FREQ IDLETIME)},
|
||||
"MEMORY" => {:subcommand, ~w(USAGE)},
|
||||
"XINFO" => {:subcommand, ~w(STREAM GROUPS CONSUMERS)},
|
||||
"XGROUP" => {:subcommand, ~w(CREATE SETID DESTROY CREATECONSUMER DELCONSUMER)}
|
||||
}
|
||||
|
||||
def tableNames, do: Map.keys(@commands)
|
||||
|
||||
def names, do: Excache.Command.known_commands() |> Enum.uniq() |> Enum.sort()
|
||||
|
||||
def known?(name), do: Map.has_key?(@commands, name)
|
||||
|
||||
def count, do: length(names())
|
||||
|
||||
def infoTerm(name) do
|
||||
case Map.fetch(@commands, name) do
|
||||
{:ok, {arity, flags, firstKey, lastKey, step, _group}} ->
|
||||
{:array,
|
||||
[
|
||||
{:bulk, String.downcase(name)},
|
||||
{:integer, arity},
|
||||
{:array, Enum.map(flags, fn flag -> {:simple, Atom.to_string(flag)} end)},
|
||||
{:integer, firstKey},
|
||||
{:integer, lastKey},
|
||||
{:integer, step}
|
||||
]}
|
||||
|
||||
:error ->
|
||||
{:array, nil}
|
||||
end
|
||||
end
|
||||
|
||||
def docsTerm(name) do
|
||||
{arity, _flags, _firstKey, _lastKey, _step, group} = Map.fetch!(@commands, name)
|
||||
|
||||
{:array,
|
||||
[
|
||||
{:bulk, "group"},
|
||||
{:bulk, Atom.to_string(group)},
|
||||
{:bulk, "arity"},
|
||||
{:integer, arity}
|
||||
]}
|
||||
end
|
||||
|
||||
def arityOk?(name, argc) do
|
||||
{arity, _flags, _firstKey, _lastKey, _step, _group} = Map.fetch!(@commands, name)
|
||||
if arity < 0, do: argc >= -arity, else: argc == arity
|
||||
end
|
||||
|
||||
def keysFor(name, args) do
|
||||
case Map.get(@keyRules, name) do
|
||||
nil -> rangeKeys(name, args)
|
||||
rule -> ruleKeys(rule, args)
|
||||
end
|
||||
end
|
||||
|
||||
defp rangeKeys(name, args) do
|
||||
{_arity, _flags, firstKey, lastKey, step, _group} = Map.fetch!(@commands, name)
|
||||
|
||||
if firstKey == 0 do
|
||||
{:ok, []}
|
||||
else
|
||||
count = length(args)
|
||||
from = firstKey - 1
|
||||
to = if lastKey < 0, do: count + lastKey, else: lastKey - 1
|
||||
|
||||
if to < from do
|
||||
{:ok, []}
|
||||
else
|
||||
{:ok, args |> Enum.slice(from..to) |> Enum.take_every(step)}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp ruleKeys(:streams, args) do
|
||||
case Enum.find_index(args, fn arg -> String.upcase(arg) == "STREAMS" end) do
|
||||
nil ->
|
||||
:error
|
||||
|
||||
index ->
|
||||
tail = Enum.drop(args, index + 1)
|
||||
half = div(length(tail), 2)
|
||||
if half == 0 or rem(length(tail), 2) == 1, do: :error, else: {:ok, Enum.take(tail, half)}
|
||||
end
|
||||
end
|
||||
|
||||
defp ruleKeys({:numkeys, position}, args) do
|
||||
with {numkeys, ""} when numkeys > 0 <- Integer.parse(Enum.at(args, position - 1, "")),
|
||||
keys when length(keys) == numkeys <- args |> Enum.drop(position) |> Enum.take(numkeys) do
|
||||
{:ok, keys}
|
||||
else
|
||||
_invalid -> :error
|
||||
end
|
||||
end
|
||||
|
||||
defp ruleKeys({:subcommand, takesKey}, [subcommand, key | _rest]) do
|
||||
if String.upcase(subcommand) in takesKey, do: {:ok, [key]}, else: {:ok, []}
|
||||
end
|
||||
|
||||
defp ruleKeys({:subcommand, _takesKey}, _args), do: {:ok, []}
|
||||
end
|
||||
Reference in new issue
Block a user