From 0b360058780222601e531115433121f3dcee147f Mon Sep 17 00:00:00 2001 From: dvora-h Date: Wed, 27 Apr 2022 16:41:36 +0300 Subject: [PATCH 1/6] add support for NOW, FORCE and ABORT modifiers --- redis/commands/core.py | 43 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/redis/commands/core.py b/redis/commands/core.py index 606256a33c..c7a89a5d03 100644 --- a/redis/commands/core.py +++ b/redis/commands/core.py @@ -1080,12 +1080,25 @@ def save(self, **kwargs) -> ResponseT: """ return self.execute_command("SAVE", **kwargs) - def shutdown(self, save: bool = False, nosave: bool = False, **kwargs) -> None: + def shutdown( + self, + save: bool = False, + nosave: bool = False, + now: bool = False, + force: bool = False, + abort: bool = False, + **kwargs, + ) -> None: """Shutdown the Redis server. If Redis has persistence configured, - data will be flushed before shutdown. If the "save" option is set, - a data flush will be attempted even if there is no persistence - configured. If the "nosave" option is set, no data flush will be - attempted. The "save" and "nosave" options cannot both be set. + data will be flushed before shutdown. + It is possible to specify modifiers to alter the behavior of the command: + ``save`` will force a DB saving operation even if no save points are configured. + ``nosave`` will prevent a DB saving operation even if one or more save points + are configured. + ``now`` skips waiting for lagging replicas, i.e. it bypasses the first step in + the shutdown sequence. + ``force`` ignores any errors that would normally prevent the server from exiting + ``abort`` cancels an ongoing shutdown and cannot be combined with other flags. For more information see https://redis.io/commands/shutdown """ @@ -1096,6 +1109,12 @@ def shutdown(self, save: bool = False, nosave: bool = False, **kwargs) -> None: args.append("SAVE") if nosave: args.append("NOSAVE") + if now: + args.append("NOW") + if force: + args.append("FORCE") + if abort: + args.append("ABORT") try: self.execute_command(*args, **kwargs) except ConnectionError: @@ -1206,7 +1225,13 @@ async def memory_help(self, **kwargs) -> None: return super().memory_help(**kwargs) async def shutdown( - self, save: bool = False, nosave: bool = False, **kwargs + self, + save: bool = False, + nosave: bool = False, + now: bool = False, + force: bool = False, + abort: bool = False, + **kwargs, ) -> None: """Shutdown the Redis server. If Redis has persistence configured, data will be flushed before shutdown. If the "save" option is set, @@ -1223,6 +1248,12 @@ async def shutdown( args.append("SAVE") if nosave: args.append("NOSAVE") + if now: + args.append("NOW") + if force: + args.append("FORCE") + if abort: + args.append("ABORT") try: await self.execute_command(*args, **kwargs) except ConnectionError: From ffe5e4974eb6164d7bed17c775dc65f76f770080 Mon Sep 17 00:00:00 2001 From: dvora-h <67596500+dvora-h@users.noreply.github.com> Date: Tue, 3 May 2022 12:25:32 +0300 Subject: [PATCH 2/6] linters --- redis/commands/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redis/commands/core.py b/redis/commands/core.py index c4ea75b068..545bd38864 100644 --- a/redis/commands/core.py +++ b/redis/commands/core.py @@ -1119,7 +1119,7 @@ def shutdown( **kwargs, ) -> None: """Shutdown the Redis server. If Redis has persistence configured, - data will be flushed before shutdown. + data will be flushed before shutdown. It is possible to specify modifiers to alter the behavior of the command: ``save`` will force a DB saving operation even if no save points are configured. ``nosave`` will prevent a DB saving operation even if one or more save points From 7c505891a05da8f8a89a2f456b146da92a398b95 Mon Sep 17 00:00:00 2001 From: dvora-h Date: Sun, 8 May 2022 15:50:07 +0300 Subject: [PATCH 3/6] test --- tests/test_commands.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/test_commands.py b/tests/test_commands.py index 59754123ac..55cda4c7db 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -3,6 +3,7 @@ import re import time from string import ascii_letters +from unittest import mock import pytest @@ -4632,6 +4633,12 @@ def test_replicaof(self, r): with pytest.raises(redis.ResponseError): assert r.replicaof("NO ONE") assert r.replicaof("NO", "ONE") + + def test_shutdown(self, r: redis.Redis): + conn = redis.Redis(port=6380) + conn.shutdown = mock.MagicMock() + conn.shutdown() + conn.shutdown.assert_called_once_with() @pytest.mark.replica @skip_if_server_version_lt("2.8.0") From 66961cd4b67a4116f47f6643ae6705c9867c3fa3 Mon Sep 17 00:00:00 2001 From: dvora-h Date: Sun, 8 May 2022 16:11:53 +0300 Subject: [PATCH 4/6] linters --- tests/test_commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_commands.py b/tests/test_commands.py index 55cda4c7db..babd97259a 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -4633,7 +4633,7 @@ def test_replicaof(self, r): with pytest.raises(redis.ResponseError): assert r.replicaof("NO ONE") assert r.replicaof("NO", "ONE") - + def test_shutdown(self, r: redis.Redis): conn = redis.Redis(port=6380) conn.shutdown = mock.MagicMock() From 1484a481aeee5987b645e8ad98806e978bda588e Mon Sep 17 00:00:00 2001 From: dvora-h Date: Mon, 9 May 2022 09:49:38 +0300 Subject: [PATCH 5/6] test params --- tests/test_commands.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/test_commands.py b/tests/test_commands.py index babd97259a..f5c513091c 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -4634,11 +4634,17 @@ def test_replicaof(self, r): assert r.replicaof("NO ONE") assert r.replicaof("NO", "ONE") - def test_shutdown(self, r: redis.Redis): - conn = redis.Redis(port=6380) - conn.shutdown = mock.MagicMock() - conn.shutdown() - conn.shutdown.assert_called_once_with() + def test_shutdown(self): + r = redis.Redis(port=6380) + r.shutdown = mock.MagicMock() + r.shutdown() + r.shutdown.assert_called_once() + + @skip_if_server_version_lt("7.0.0") + def test_shutdown_with_params(self): + r = redis.Redis(port=6380) + r.shutdown(save=True, now=True, force=True, abort=False) + r.shutdown.assert_called_with(save=True, now=True, force=True, abort=False) @pytest.mark.replica @skip_if_server_version_lt("2.8.0") From 461f59eafb3856babbde96efb3922cc5caf66fc1 Mon Sep 17 00:00:00 2001 From: dvora-h Date: Wed, 1 Jun 2022 15:39:51 +0300 Subject: [PATCH 6/6] fix tests --- tests/test_commands.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/test_commands.py b/tests/test_commands.py index f5c513091c..92a63c9d9e 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -4634,17 +4634,18 @@ def test_replicaof(self, r): assert r.replicaof("NO ONE") assert r.replicaof("NO", "ONE") - def test_shutdown(self): - r = redis.Redis(port=6380) - r.shutdown = mock.MagicMock() - r.shutdown() - r.shutdown.assert_called_once() + def test_shutdown(self, r: redis.Redis): + r.execute_command = mock.MagicMock() + r.execute_command("SHUTDOWN", "NOSAVE") + r.execute_command.assert_called_once_with("SHUTDOWN", "NOSAVE") @skip_if_server_version_lt("7.0.0") - def test_shutdown_with_params(self): - r = redis.Redis(port=6380) - r.shutdown(save=True, now=True, force=True, abort=False) - r.shutdown.assert_called_with(save=True, now=True, force=True, abort=False) + def test_shutdown_with_params(self, r: redis.Redis): + r.execute_command = mock.MagicMock() + r.execute_command("SHUTDOWN", "SAVE", "NOW", "FORCE") + r.execute_command.assert_called_once_with("SHUTDOWN", "SAVE", "NOW", "FORCE") + r.execute_command("SHUTDOWN", "ABORT") + r.execute_command.assert_called_with("SHUTDOWN", "ABORT") @pytest.mark.replica @skip_if_server_version_lt("2.8.0")