fix(kafka): support legacy topic metadata and config gaps

Closes #6217
This commit is contained in:
t8y2 committed 2026-08-14 07:01:07 +00:00
1 parent df95288aab
commit 9e730fac56
5 files changed
+262 -5

No files matched your search

@@ -4,7 +4,7 @@ import { computed, ref, watch } from "vue";
import { useI18n } from "vue-i18n";
import type { BacklogQuota, DispatchRate, PolicyScope, PublishRate, RetentionPolicy, SubscribeRate, TopicInfo } from "@/types/mq";
import { mqGetEffectivePolicies, mqSetBacklogQuota, mqSetDispatchRate, mqSetPublishRate, mqSetRetention, mqSetSubscribeRate } from "@/lib/backend/api";
import { defaultMqPolicyForms, policyFormsFromEffectivePolicies } from "@/lib/mq/mqPolicyForms";
import { defaultMqPolicyForms, policyAccessFromEffectivePolicies, policyFormsFromEffectivePolicies } from "@/lib/mq/mqPolicyForms";
import { useMqMutationGuard } from "@/composables/useMqMutationGuard";
interface Props {
@@ -29,6 +29,7 @@ const error = ref<string>();
const notice = ref<string>();
const readOnlyMessage = computed(() => t("mqPolicies.readOnly"));
const defaultForms = defaultMqPolicyForms();
const policyAccess = ref(policyAccessFromEffectivePolicies(undefined));
const publishForm = ref<PublishRate>({ ...defaultForms.publishForm });
@@ -84,6 +85,7 @@ async function guardWritable(operation: string): Promise<boolean> {
async function loadPolicies() {
const current = scope.value;
policies.value = undefined;
policyAccess.value = policyAccessFromEffectivePolicies(undefined);
notice.value = undefined;
error.value = undefined;
if (!current) return;
@@ -92,6 +94,7 @@ async function loadPolicies() {
try {
const loaded = await mqGetEffectivePolicies(props.connectionId, current);
policies.value = loaded;
policyAccess.value = policyAccessFromEffectivePolicies(loaded);
const hydrated = policyFormsFromEffectivePolicies(loaded, defaultMqPolicyForms());
applyPolicyForms(hydrated);
} catch (e: unknown) {
@@ -189,7 +192,8 @@ watch(
<div v-if="error" class="panel-error">{{ error }}</div>
<div v-if="notice" class="panel-notice">{{ notice }}</div>
<div class="policy-grid">
<div v-if="!policyAccess.readable" class="readonly-hint">{{ policyAccess.unsupportedReason }}</div>
<div v-else class="policy-grid">
<section v-if="supportsRateLimits !== false" class="policy-section">
<h4>{{ t("mqPolicies.publishRate") }}</h4>
<label>
+21 -1
View File
@@ -1,7 +1,27 @@
import { describe, expect, it } from "vitest";
import { defaultMqPolicyForms, policyFormsFromEffectivePolicies } from "@/lib/mq/mqPolicyForms";
import { defaultMqPolicyForms, policyAccessFromEffectivePolicies, policyFormsFromEffectivePolicies } from "@/lib/mq/mqPolicyForms";
describe("mqPolicyForms", () => {
it("keeps ordinary policy responses available", () => {
expect(policyAccessFromEffectivePolicies({ configs: {} })).toEqual({
readable: true,
unsupportedReason: undefined,
});
});
it("marks legacy Kafka configuration responses as unavailable with a reason", () => {
expect(
policyAccessFromEffectivePolicies({
configs: {},
configSupported: false,
unsupportedReason: "The broker does not support DescribeConfigs.",
}),
).toEqual({
readable: false,
unsupportedReason: "The broker does not support DescribeConfigs.",
});
});
it("hydrates forms from topic effective policies", () => {
const forms = policyFormsFromEffectivePolicies(
{
+14
View File
@@ -8,6 +8,11 @@ export interface MqPolicyForms {
retentionForm: RetentionPolicy;
}
export interface MqPolicyAccess {
readable: boolean;
unsupportedReason?: string;
}
export function defaultMqPolicyForms(): MqPolicyForms {
return {
publishForm: {
@@ -36,6 +41,15 @@ export function defaultMqPolicyForms(): MqPolicyForms {
};
}
export function policyAccessFromEffectivePolicies(raw: unknown): MqPolicyAccess {
const root = objectRecord(raw);
const readable = root.configSupported !== false;
return {
readable,
unsupportedReason: readable ? undefined : stringField(root.unsupportedReason),
};
}
export function policyFormsFromEffectivePolicies(raw: unknown, fallback: MqPolicyForms): MqPolicyForms {
const root = objectRecord(raw);
const topicPolicies = objectRecord(root.topicPolicies);