Files
scylladb/test/cluster/mv/test_mv_simple.py
Dawid Mędrek b409e85c20 view: Stop requiring experimental feature
We modify the requirements for using materialized views in tablet-based
keyspaces. Before, it was necessary to enable the configuration option
`rf_rack_valid_keyspaces`, having the cluster feature `VIEWS_WITH_TABLETS`
enabled, and using the experimental feature `views-with-tablets`.
We drop the last requirement.

We adjust code to that change and provide a new validation test.
We also update the user documentation to reflect the changes.

Fixes scylladb/scylladb#23030
2025-10-01 09:01:53 +02:00

121 lines
5.2 KiB
Python

#
# Copyright (C) 2025-present ScyllaDB
#
# SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
#
import asyncio
import logging
import pytest
from cassandra.cluster import Session as CassandraSession
from cassandra.protocol import InvalidRequest
from test.pylib.manager_client import ManagerClient
logger = logging.getLogger(__name__)
@pytest.mark.asyncio
@pytest.mark.parametrize("schema_kind", ["view", "index"])
# Views no longer depend on the experimental feature `views-with-tablets`,
# but let's keep these test cases to make sure it's really not needed anymore.
@pytest.mark.parametrize("views_with_tablets", [False, True])
@pytest.mark.parametrize("rf_rack_valid_keyspaces", [False, True])
async def test_mv_and_index_restrictions_in_tablet_keyspaces(manager: ManagerClient, schema_kind: str,
views_with_tablets: bool, rf_rack_valid_keyspaces: bool):
"""
Verify that creating a materialized view or a secondary index in a tablet-based keyspace
is only possible when both the configuration option `rf_rack_valid_keyspaces` is enabled.
"""
async def create_mv_or_index(cql: CassandraSession):
if schema_kind == "view":
await cql.run_async("CREATE MATERIALIZED VIEW ks.mv "
"AS SELECT * FROM ks.t "
"WHERE p IS NOT NULL AND v IS NOT NULL "
"PRIMARY KEY (v, p)")
elif schema_kind == "index":
await cql.run_async("CREATE INDEX myindex ON ks.t(v)")
else:
assert False, "Unknown schema kind"
async def try_pass(cql: CassandraSession):
try:
await cql.run_async(f"CREATE KEYSPACE ks WITH replication = "
"{'class': 'NetworkTopologyStrategy', 'replication_factor': 1} "
"AND tablets = {'enabled': true}")
await cql.run_async(f"CREATE TABLE ks.t (p int PRIMARY KEY, v int)")
await create_mv_or_index(cql)
finally:
await cql.run_async(f"DROP KEYSPACE IF EXISTS ks")
async def try_fail(cql: CassandraSession):
err = "Materialized views and secondary indexes are not supported on base tables with tablets. " \
"To be able to use them, enable the configuration option `rf_rack_valid_keyspaces` and " \
"make sure that the cluster feature `VIEWS_WITH_TABLETS` is enabled."
with pytest.raises(InvalidRequest, match=err):
await try_pass(cql)
feature = ["views-with-tablets"] if views_with_tablets else []
config = {"experimental_features": feature, "rf_rack_valid_keyspaces": rf_rack_valid_keyspaces}
srv = await manager.server_add(config=config)
# Necessary because we're restarting the node multiple times.
cql, _ = await manager.get_ready_cql([srv])
logger.debug("Obtained CassandraSession object")
# We just want to validate the statements. We don't need to wait.
assert hasattr(cql.cluster, "max_schema_agreement_wait")
cql.cluster.max_schema_agreement_wait = 0
logger.debug("Set max_schema_agreement_wait to 0")
if rf_rack_valid_keyspaces:
await try_pass(cql)
logger.debug("try_pass finished successfully")
else:
await try_fail(cql)
logger.debug("try_fail finished successfully")
@pytest.mark.asyncio
@pytest.mark.parametrize("view_type", ["view", "index"])
async def test_view_startup(manager: ManagerClient, view_type: str):
"""
Verify that starting a node with materialized views in a tablet-based
keyspace when the configuration option `rf_rack_valid_keyspaces` is disabled
leads to a warning.
"""
srv = await manager.server_add(config={"rf_rack_valid_keyspaces": True})
cql = manager.get_cql()
await cql.run_async("CREATE KEYSPACE ks WITH replication = "
"{'class': 'NetworkTopologyStrategy', 'replication_factor': 1} "
"AND tablets = {'enabled': true}")
await cql.run_async("CREATE TABLE ks.t (p int PRIMARY KEY, v int)")
if view_type == "view":
await cql.run_async("CREATE MATERIALIZED VIEW ks.mv "
"AS SELECT * FROM ks.t "
"WHERE p IS NOT NULL AND v IS NOT NULL "
"PRIMARY KEY (v, p)")
elif view_type == "index":
await cql.run_async("CREATE INDEX i ON ks.t(v)")
else:
logger.error(f"Unexpected view type: {view_type}")
assert False
await manager.server_stop(srv.server_id)
await manager.server_update_config(srv.server_id, "rf_rack_valid_keyspaces", False)
log = await manager.server_open_log(srv.server_id)
mark = await log.mark()
start_task = asyncio.create_task(manager.server_start(srv.server_id))
err = "Some of the existing keyspaces violate the requirements for using materialized " \
"views or secondary indexes. Those features require enabling the configuration " \
"option `rf_rack_valid_keyspaces` and the cluster feature `VIEWS_WITH_TABLETS`. " \
"The keyspaces that violate that condition: ks"
await log.wait_for(err, from_mark=mark)
await start_task