Skip to content

Commit

Permalink
Python: add FUNCTION FLUSH command (#1700)
Browse files Browse the repository at this point in the history
* Python: Added FUNCTION LOAD command

* Python: adds FUNCTION FLUSH command

* Updated CHANGELOG.md

* Resolved merge issues related to FlushMode

* Minor adjustments on command documentation

* Revert one minor change in example.

---------

Co-authored-by: Shoham Elias <shohame@amazon.com>
Co-authored-by: Andrew Carbonetto <andrew.carbonetto@improving.com>
  • Loading branch information
3 people authored Jun 28, 2024
1 parent 1df349b commit 1c00333
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
* Python: Added FUNCTION LOAD command ([#1699](https://github.com/aws/glide-for-redis/pull/1699))
* Python: Added XPENDING command ([#1704](https://github.com/aws/glide-for-redis/pull/1704))
* Python: Added RANDOMKEY command ([#1701](https://github.com/aws/glide-for-redis/pull/1701))
* Python: Added FUNCTION FLUSH command ([#1700](https://github.com/aws/glide-for-redis/pull/1700))

### Breaking Changes
* Node: Update XREAD to return a Map of Map ([#1494](https://github.com/aws/glide-for-redis/pull/1494))
Expand Down
31 changes: 31 additions & 0 deletions python/python/glide/async_commands/cluster_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,37 @@ async def function_load(
),
)

async def function_flush(
self, mode: Optional[FlushMode] = None, route: Optional[Route] = None
) -> TOK:
"""
Deletes all function libraries.
See https://valkey.io/docs/latest/commands/function-flush/ for more details.
Args:
mode (Optional[FlushMode]): The flushing mode, could be either `SYNC` or `ASYNC`.
route (Optional[Route]): The command will be routed to all primaries, unless `route` is provided,
in which case the client will route the command to the nodes defined by `route`.
Returns:
TOK: A simple `OK`.
Examples:
>>> await client.function_flush(FlushMode.SYNC)
"OK"
Since: Redis 7.0.0.
"""
return cast(
TOK,
await self._execute_command(
RequestType.FunctionFlush,
[mode.value] if mode else [],
route,
),
)

async def time(self, route: Optional[Route] = None) -> TClusterResponse[List[str]]:
"""
Returns the server time.
Expand Down
26 changes: 26 additions & 0 deletions python/python/glide/async_commands/standalone_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,32 @@ async def function_load(self, library_code: str, replace: bool = False) -> str:
),
)

async def function_flush(self, mode: Optional[FlushMode] = None) -> TOK:
"""
Deletes all function libraries.
See https://valkey.io/docs/latest/commands/function-flush/ for more details.
Args:
mode (Optional[FlushMode]): The flushing mode, could be either `SYNC` or `ASYNC`.
Returns:
TOK: A simple `OK`.
Examples:
>>> await client.function_flush(FlushMode.SYNC)
"OK"
Since: Redis 7.0.0.
"""
return cast(
TOK,
await self._execute_command(
RequestType.FunctionFlush,
[mode.value] if mode else [],
),
)

async def time(self) -> List[str]:
"""
Returns the server time.
Expand Down
21 changes: 21 additions & 0 deletions python/python/glide/async_commands/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -1801,6 +1801,27 @@ def function_load(
["REPLACE", library_code] if replace else [library_code],
)

def function_flush(
self: TTransaction, mode: Optional[FlushMode] = None
) -> TTransaction:
"""
Deletes all function libraries.
See https://valkey.io/docs/latest/commands/function-flush/ for more details.
Args:
mode (Optional[FlushMode]): The flushing mode, could be either `SYNC` or `ASYNC`.
Commands response:
TOK: A simple `OK`.
Since: Redis 7.0.0.
"""
return self.append_command(
RequestType.FunctionFlush,
[mode.value] if mode else [],
)

def xadd(
self: TTransaction,
key: str,
Expand Down
60 changes: 60 additions & 0 deletions python/python/tests/test_async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6731,6 +6731,66 @@ async def test_function_load_cluster_with_route(

assert await redis_client.function_load(new_code, True, route) == lib_name

@pytest.mark.parametrize("cluster_mode", [True, False])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
async def test_function_flush(self, redis_client: TGlideClient):
min_version = "7.0.0"
if await check_if_server_version_lt(redis_client, min_version):
pytest.skip(f"Redis version required >= {min_version}")

lib_name = f"mylib1C{get_random_string(5)}"
func_name = f"myfunc1c{get_random_string(5)}"
code = generate_lua_lib_code(lib_name, {func_name: "return args[1]"}, True)

# Load the function
assert await redis_client.function_load(code) == lib_name

# TODO: Ensure the function exists with FUNCTION LIST

# Flush functions
assert await redis_client.function_flush(FlushMode.SYNC) == OK
assert await redis_client.function_flush(FlushMode.ASYNC) == OK

# TODO: Ensure the function is no longer present with FUNCTION LIST

# Attempt to re-load library without overwriting to ensure FLUSH was effective
assert await redis_client.function_load(code) == lib_name

# Clean up by flushing functions again
await redis_client.function_flush()

@pytest.mark.parametrize("cluster_mode", [True])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
@pytest.mark.parametrize("single_route", [True, False])
async def test_function_flush_with_routing(
self, redis_client: GlideClusterClient, single_route: bool
):
min_version = "7.0.0"
if await check_if_server_version_lt(redis_client, min_version):
pytest.skip(f"Redis version required >= {min_version}")

lib_name = f"mylib1C{get_random_string(5)}"
func_name = f"myfunc1c{get_random_string(5)}"
code = generate_lua_lib_code(lib_name, {func_name: "return args[1]"}, True)
route = SlotKeyRoute(SlotType.PRIMARY, "1") if single_route else AllPrimaries()

# Load the function
assert await redis_client.function_load(code, False, route) == lib_name

# TODO: Ensure the function exists with FUNCTION LIST

# Flush functions
assert await redis_client.function_flush(FlushMode.SYNC, route) == OK
assert await redis_client.function_flush(FlushMode.ASYNC, route) == OK

# TODO: Ensure the function is no longer present with FUNCTION LIST

# Attempt to re-load library without overwriting to ensure FLUSH was effective
assert await redis_client.function_load(code, False, route) == lib_name

# Clean up by flushing functions again
assert await redis_client.function_flush(route=route) == OK

@pytest.mark.parametrize("cluster_mode", [True, False])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
async def test_srandmember(self, redis_client: TGlideClient):
Expand Down
6 changes: 6 additions & 0 deletions python/python/tests/test_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ async def transaction_test(
args.append(lib_name)
transaction.function_load(code, True)
args.append(lib_name)
transaction.function_flush()
args.append(OK)
transaction.function_flush(FlushMode.ASYNC)
args.append(OK)
transaction.function_flush(FlushMode.SYNC)
args.append(OK)

transaction.dbsize()
args.append(0)
Expand Down

0 comments on commit 1c00333

Please sign in to comment.