Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 63 additions & 1 deletion console/src/api/materialize/cluster/clusterList.test.sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0.

import { executeSqlHttp } from "~/test/sql/materializeSqlClient";
import {
executeSqlHttp,
getMaterializeClient,
} from "~/test/sql/materializeSqlClient";
import { testdrive } from "~/test/sql/mzcompose";

import { buildClustersQuery } from "./clusterList";
Expand Down Expand Up @@ -88,4 +91,63 @@ describe("buildClusterSubscribe", () => {
},
]);
});

it("correctly associates statuses with multiple replicas", async () => {
const client = await getMaterializeClient();

await testdrive(
`> CREATE CLUSTER test_multi (SIZE 'scale=1,workers=1', REPLICATION FACTOR 2);`,
);

try {
const {
rows: [cluster],
} = await client.query<{ id: string }>(
"SELECT id FROM mz_clusters WHERE name = 'test_multi'",
);
const { rows: replicas } = await client.query<{
id: string;
name: string;
}>(
`SELECT id, name FROM mz_cluster_replicas WHERE cluster_id = '${cluster.id}' ORDER BY name`,
);
const [r1, r2] = replicas;

// Wait for both replicas to have statuses
const waitForStatuses = async () => {
for (let i = 0; i < 30; i++) {
const { rows } = await client.query<{ count: string }>(
`SELECT COUNT(DISTINCT replica_id)::text as count FROM mz_cluster_replica_statuses WHERE replica_id IN ('${r1.id}', '${r2.id}')`,
);
if (rows[0].count === "2") return;
await new Promise((resolve) => setTimeout(resolve, 1000));
}
throw new Error("Timed out waiting for replica statuses");
};
await waitForStatuses();

const query = buildClustersQuery({
queryOwnership: false,
includeSystemObjects: false,
}).compile();
const result = await executeSqlHttp(query);

const testCluster = result.rows.find((r) => r.name === "test_multi");
expect(testCluster).toBeDefined();
expect(testCluster!.replicas).toHaveLength(2);

const replicaR1 = testCluster!.replicas.find((r) => r.name === "r1");
const replicaR2 = testCluster!.replicas.find((r) => r.name === "r2");

// Each replica's statuses should only contain its own replica_id
expect(replicaR1!.statuses).toEqual([
expect.objectContaining({ replica_id: r1.id }),
]);
expect(replicaR2!.statuses).toEqual([
expect.objectContaining({ replica_id: r2.id }),
]);
} finally {
await testdrive(`> DROP CLUSTER IF EXISTS test_multi;`);
}
});
});
6 changes: 3 additions & 3 deletions console/src/api/materialize/cluster/clusterList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ export const buildClustersQuery = ({
}>(
eb
.selectFrom("mz_cluster_replicas as cr")
.select([
.select((replicaEb) => [
"cr.id",
"cr.name",
"cr.size",
"cr.disk",
jsonArrayFrom(
eb
replicaEb
.selectFrom("mz_cluster_replica_statuses as crs_inner")
.select([
"crs_inner.replica_id",
Expand All @@ -89,7 +89,7 @@ export const buildClustersQuery = ({
"crs_inner.reason",
"crs_inner.updated_at",
])
.whereRef("crs_inner.replica_id", "=", "c.id"),
.whereRef("crs_inner.replica_id", "=", "cr.id"),
).as("statuses"),
])
.whereRef("cr.cluster_id", "=", "c.id")
Expand Down