fix(server): Fix QUIT not shutting down connection (#280)

* fix(server): Fix QUIT not shutting down connection

Fixes #170
This commit is contained in:
Vladislav 2022-09-13 05:25:46 +03:00 committed by GitHub
parent 0fbd1afa36
commit add252c301
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 35 additions and 6 deletions

View File

@ -698,6 +698,10 @@ auto Connection::FromArgs(RespVec args, mi_heap_t* heap) -> Request* {
return req; return req;
} }
void Connection::ShutdownSelf() {
util::Connection::Shutdown();
}
void RespToArgList(const RespVec& src, CmdArgVec* dest) { void RespToArgList(const RespVec& src, CmdArgVec* dest) {
dest->resize(src.size()); dest->resize(src.size());
for (size_t i = 0; i < src.size(); ++i) { for (size_t i = 0; i < src.size(); ++i) {

View File

@ -72,6 +72,8 @@ class Connection : public util::Connection {
std::string GetClientInfo() const; std::string GetClientInfo() const;
uint32 GetClientId() const; uint32 GetClientId() const;
void ShutdownSelf();
protected: protected:
void OnShutdown() override; void OnShutdown() override;
void OnPreMigrateThread() override; void OnPreMigrateThread() override;

View File

@ -721,6 +721,7 @@ void Service::Quit(CmdArgList args, ConnectionContext* cntx) {
SinkReplyBuilder* builder = cntx->reply_builder(); SinkReplyBuilder* builder = cntx->reply_builder();
builder->CloseConnection(); builder->CloseConnection();
cntx->owner()->ShutdownSelf();
} }
void Service::Multi(CmdArgList args, ConnectionContext* cntx) { void Service::Multi(CmdArgList args, ConnectionContext* cntx) {

View File

@ -48,7 +48,7 @@ def df_server(request, tmp_dir: Path, test_env):
arguments = [arg.format(**test_env) for arg in request.param] arguments = [arg.format(**test_env) for arg in request.param]
dfly_proc = subprocess.Popen([DRAGONFLY_PATH, *arguments], dfly_proc = subprocess.Popen([DRAGONFLY_PATH, *arguments],
env=test_env, cwd=str(tmp_dir)) env=test_env, cwd=str(tmp_dir))
time.sleep(0.1) time.sleep(0.3)
return_code = dfly_proc.poll() return_code = dfly_proc.poll()
if return_code is not None: if return_code is not None:
dfly_proc.terminate() dfly_proc.terminate()
@ -66,17 +66,19 @@ def df_server(request, tmp_dir: Path, test_env):
print(outs) print(outs)
print(errs) print(errs)
@pytest.fixture(scope="function")
def connection(df_server):
return redis.Connection()
@pytest.fixture(scope="class") @pytest.fixture(scope="class")
def connection(df_server): def raw_client(df_server):
""" Creates the Redis client to interact with the Dragonfly instance """ """ Creates the Redis client to interact with the Dragonfly instance """
pool = redis.ConnectionPool(decode_responses=True) pool = redis.ConnectionPool(decode_responses=True)
client = redis.Redis(connection_pool=pool) client = redis.Redis(connection_pool=pool)
return client return client
@pytest.fixture @pytest.fixture
def client(connection): def client(raw_client):
""" Flushes all the records, runs before each test. """ """ Flushes all the records, runs before each test. """
connection.flushall() raw_client.flushall()
return connection return raw_client

View File

@ -0,0 +1,20 @@
import pytest
import redis
def test_quit(connection):
connection.send_command("QUIT")
assert connection.read_response() == b'OK'
with pytest.raises(redis.exceptions.ConnectionError) as e:
connection.read_response()
def test_quit_after_sub(connection):
connection = redis.Connection()
connection.send_command("SUBSCRIBE", "foo")
connection.read_response()
connection.send_command("QUIT")
assert connection.read_response() == b'OK'
with pytest.raises(redis.exceptions.ConnectionError) as e:
connection.read_response()