Files
scylladb/test/nodetool/test_compactionstats.py
Avi Kivity f3eade2f62 treewide: relicense to ScyllaDB-Source-Available-1.0
Drop the AGPL license in favor of a source-available license.
See the blog post [1] for details.

[1] https://www.scylladb.com/2024/12/18/why-were-moving-to-a-source-available-license/
2024-12-18 17:45:13 +02:00

100 lines
3.5 KiB
Python

#
# Copyright 2024-present ScyllaDB
#
# SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
#
import pytest
from datetime import timedelta
from uuid import uuid1
from test.nodetool.rest_api_mock import expected_request
def create_task(i, num_pending_tasks):
return {"ks": "ks",
"cf": f"cf{i}",
"task": num_pending_tasks}
def create_compaction_stats(ks, cf):
return {"id": str(uuid1()),
"ks": ks,
"cf": cf,
"unit": "keys",
"completed": 42,
"total": 10240,
"task_type": "COMPACTION"}
def format_task(task):
ks = task["ks"]
cf = task["cf"]
num = task["task"]
return f"- {ks}.{cf}: {num}\n"
def format_compaction(compaction, progress=None):
task_id = compaction['id']
task_type = compaction['task_type']
keyspace = compaction['ks']
table = compaction['cf']
completed = compaction['completed']
total = compaction['total']
unit = compaction['unit']
if progress is None:
percent = completed * 100 / total
progress = f"{percent:.2f}%"
return f'{task_id:<36} {task_type:<15} {keyspace:<8} {table:<5} {completed:<9} {total:<5} {unit:<4} {progress:<8}\n'
@pytest.mark.parametrize("num_compactions", [0, 1, 2])
@pytest.mark.parametrize("throughput", [0, 1024])
def test_compactionstats(nodetool, request, num_compactions, throughput):
pending_tasks = [create_task(i, 1) for i in range(num_compactions)]
compactions = [create_compaction_stats(task["ks"], task["cf"])
for task in pending_tasks]
expected_requests = [
expected_request("GET", "/compaction_manager/metrics/pending_tasks_by_table",
response=pending_tasks),
expected_request("GET", "/compaction_manager/compactions",
response=compactions),
]
if request.config.getoption("nodetool") == "cassandra" or len(compactions) > 0:
# scylla nodetool does not bother reading throughput if there is no
# pending compaction. but cassandra's nodetool always does.
expected_requests.append(
expected_request("GET", "/storage_service/compaction_throughput",
response=throughput))
res = nodetool("compactionstats", expected_requests=expected_requests)
actual_output = res.stdout
expected_output = f"pending tasks: {num_compactions}\n"
for task in pending_tasks:
expected_output += format_task(task)
expected_output += "\n"
if num_compactions > 0:
header = {"id": "id",
"task_type": "compaction type",
"ks": "keyspace",
"cf": "table",
"completed": "completed",
"total": "total",
"unit": "unit"}
expected_output += format_compaction(header, progress="progress")
remaining_bytes = 0
for compaction in compactions:
expected_output += format_compaction(compaction)
remaining_bytes += compaction['total'] - compaction['completed']
remaining_time = 'n/a'
if throughput > 0:
remaining_secs = remaining_bytes // (throughput * 1024 * 1024)
hours, remainder = divmod(remaining_secs, timedelta(hours=1).seconds)
minutes, seconds = divmod(remainder, timedelta(minutes=1).seconds)
remaining_time = f'{hours}h{minutes:0>2}m{seconds:0>2}s'
expected_output += f'Active compaction remaining time : {remaining_time:>10}\n'
assert actual_output == expected_output