2021-02-08 21:19:32 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
import random
|
|
|
|
import string
|
|
|
|
import time
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
from helpers.cluster import ClickHouseCluster
|
|
|
|
from helpers.network import PartitionManager
|
|
|
|
|
|
|
|
cluster = ClickHouseCluster(__file__)
|
|
|
|
node1 = cluster.add_instance(
|
2023-12-18 22:07:00 +00:00
|
|
|
"node1",
|
|
|
|
with_zookeeper=True,
|
|
|
|
main_configs=["configs/server.xml", "configs/timeouts_for_fetches.xml"],
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2021-02-08 21:19:32 +00:00
|
|
|
|
|
|
|
node2 = cluster.add_instance(
|
2023-12-18 22:07:00 +00:00
|
|
|
"node2",
|
|
|
|
with_zookeeper=True,
|
|
|
|
stay_alive=True,
|
|
|
|
main_configs=["configs/server.xml", "configs/timeouts_for_fetches.xml"],
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2021-02-08 21:19:32 +00:00
|
|
|
|
2023-12-18 21:39:59 +00:00
|
|
|
config = """
|
|
|
|
<clickhouse>
|
|
|
|
<replicated_fetches_http_connection_timeout>30</replicated_fetches_http_connection_timeout>
|
|
|
|
<replicated_fetches_http_receive_timeout>1</replicated_fetches_http_receive_timeout>
|
|
|
|
</clickhouse>
|
|
|
|
"""
|
|
|
|
|
2021-02-08 21:19:32 +00:00
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
def started_cluster():
|
|
|
|
try:
|
|
|
|
cluster.start()
|
|
|
|
|
|
|
|
yield cluster
|
|
|
|
|
|
|
|
finally:
|
|
|
|
cluster.shutdown()
|
|
|
|
|
|
|
|
|
|
|
|
def get_random_string(length):
|
2022-03-22 16:39:58 +00:00
|
|
|
return "".join(
|
|
|
|
random.choice(string.ascii_uppercase + string.digits) for _ in range(length)
|
|
|
|
)
|
2021-02-08 21:19:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_no_stall(started_cluster):
|
|
|
|
for instance in started_cluster.instances.values():
|
2022-03-22 16:39:58 +00:00
|
|
|
instance.query(
|
|
|
|
"""
|
2021-02-08 21:19:32 +00:00
|
|
|
CREATE TABLE t (key UInt64, data String)
|
|
|
|
ENGINE = ReplicatedMergeTree('/clickhouse/test/t', '{instance}')
|
|
|
|
ORDER BY tuple()
|
2022-03-22 16:39:58 +00:00
|
|
|
PARTITION BY key"""
|
|
|
|
)
|
2021-02-08 21:19:32 +00:00
|
|
|
|
|
|
|
# Pause node3 until the test setup is prepared
|
|
|
|
node2.query("SYSTEM STOP FETCHES t")
|
|
|
|
|
2022-03-22 16:39:58 +00:00
|
|
|
node1.query(
|
2023-12-18 21:39:59 +00:00
|
|
|
f"INSERT INTO t SELECT 1, '{get_random_string(104857)}' FROM numbers(500)"
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
|
|
|
node1.query(
|
2023-12-18 21:39:59 +00:00
|
|
|
f"INSERT INTO t SELECT 2, '{get_random_string(104857)}' FROM numbers(500)"
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2021-02-08 21:19:32 +00:00
|
|
|
|
|
|
|
with PartitionManager() as pm:
|
|
|
|
pm.add_network_delay(node1, 2000)
|
|
|
|
node2.query("SYSTEM START FETCHES t")
|
|
|
|
|
|
|
|
# Wait for timeout exceptions to confirm that timeout is triggered.
|
|
|
|
while True:
|
2022-03-22 16:39:58 +00:00
|
|
|
conn_timeout_exceptions = int(
|
|
|
|
node2.query(
|
|
|
|
"""
|
2021-02-08 21:19:32 +00:00
|
|
|
SELECT count()
|
|
|
|
FROM system.replication_queue
|
|
|
|
WHERE last_exception LIKE '%connect timed out%'
|
2022-03-22 16:39:58 +00:00
|
|
|
"""
|
|
|
|
)
|
|
|
|
)
|
2021-02-08 21:19:32 +00:00
|
|
|
|
|
|
|
if conn_timeout_exceptions >= 2:
|
|
|
|
break
|
|
|
|
|
|
|
|
time.sleep(0.1)
|
|
|
|
|
|
|
|
print("Connection timeouts tested!")
|
|
|
|
|
2023-12-18 21:39:59 +00:00
|
|
|
node2.replace_config(
|
2023-12-18 22:07:00 +00:00
|
|
|
"/etc/clickhouse-server/config.d/timeouts_for_fetches.xml", config
|
2022-03-22 16:39:58 +00:00
|
|
|
)
|
2021-02-08 21:19:32 +00:00
|
|
|
|
2023-12-18 21:39:59 +00:00
|
|
|
node2.restart_clickhouse()
|
|
|
|
|
2021-02-08 21:19:32 +00:00
|
|
|
while True:
|
2022-03-22 16:39:58 +00:00
|
|
|
timeout_exceptions = int(
|
|
|
|
node2.query(
|
|
|
|
"""
|
2021-02-08 21:19:32 +00:00
|
|
|
SELECT count()
|
|
|
|
FROM system.replication_queue
|
2021-07-15 08:58:21 +00:00
|
|
|
WHERE last_exception LIKE '%Timeout%'
|
2021-02-08 21:19:32 +00:00
|
|
|
AND last_exception NOT LIKE '%connect timed out%'
|
2022-03-22 16:39:58 +00:00
|
|
|
"""
|
|
|
|
).strip()
|
|
|
|
)
|
2021-02-08 21:19:32 +00:00
|
|
|
|
|
|
|
if timeout_exceptions >= 2:
|
|
|
|
break
|
|
|
|
|
|
|
|
time.sleep(0.1)
|
|
|
|
|
|
|
|
for instance in started_cluster.instances.values():
|
|
|
|
# Workaround for DROP TABLE not finishing if it is started while table is readonly.
|
|
|
|
instance.query("SYSTEM RESTART REPLICA t")
|
|
|
|
|
|
|
|
# Cleanup data directory from test results archive.
|
|
|
|
instance.query("DROP TABLE t SYNC")
|