perf(config): skip duplicate channel legacy rule loads

This commit is contained in:
Vincent Koc
2026-04-14 17:08:13 +01:00
parent f366c38df8
commit 34afe10b00
3 changed files with 60 additions and 5 deletions

View File

@@ -136,4 +136,35 @@ describe("collectChannelLegacyConfigRules", () => {
expect(loadBundledChannelDoctorContractApiMock).toHaveBeenCalledTimes(1);
expect(loadBundledChannelDoctorContractApiMock).toHaveBeenCalledWith("discord");
});
it("skips channel ids already covered by explicit legacy rules", () => {
loadBundledChannelDoctorContractApiMock.mockImplementation((channelId: string) => ({
legacyConfigRules: [
{
path: ["channels", channelId],
message: `legacy ${channelId} rule`,
},
],
}));
const rules = collectChannelLegacyConfigRules(
{
channels: {
discord: {},
telegram: {},
},
},
undefined,
new Set(["telegram"]),
);
expect(rules).toEqual([
{
path: ["channels", "discord"],
message: "legacy discord rule",
},
]);
expect(loadBundledChannelDoctorContractApiMock).toHaveBeenCalledTimes(1);
expect(loadBundledChannelDoctorContractApiMock).toHaveBeenCalledWith("discord");
});
});

View File

@@ -38,10 +38,14 @@ function shouldIncludeLegacyRuleForTouchedPaths(
function collectRelevantChannelIdsForTouchedPaths(params: {
raw?: unknown;
touchedPaths?: ReadonlyArray<ReadonlyArray<string>>;
excludedChannelIds?: ReadonlySet<ChannelId>;
}): ChannelId[] {
const channelIds = collectConfiguredChannelIds(params.raw);
const filteredChannelIds = params.excludedChannelIds?.size
? channelIds.filter((channelId) => !params.excludedChannelIds?.has(channelId))
: channelIds;
if (!params.touchedPaths || params.touchedPaths.length === 0) {
return channelIds;
return filteredChannelIds;
}
const touchedChannelIds = new Set<ChannelId>();
@@ -51,7 +55,7 @@ function collectRelevantChannelIdsForTouchedPaths(params: {
continue;
}
if (!second) {
return channelIds;
return filteredChannelIds;
}
if (second === "defaults") {
continue;
@@ -62,14 +66,19 @@ function collectRelevantChannelIdsForTouchedPaths(params: {
if (touchedChannelIds.size === 0) {
return [];
}
return channelIds.filter((channelId) => touchedChannelIds.has(channelId));
return filteredChannelIds.filter((channelId) => touchedChannelIds.has(channelId));
}
export function collectChannelLegacyConfigRules(
raw?: unknown,
touchedPaths?: ReadonlyArray<ReadonlyArray<string>>,
excludedChannelIds?: ReadonlySet<ChannelId>,
): LegacyConfigRule[] {
const channelIds = collectRelevantChannelIdsForTouchedPaths({ raw, touchedPaths });
const channelIds = collectRelevantChannelIdsForTouchedPaths({
raw,
touchedPaths,
excludedChannelIds,
});
const rules: LegacyConfigRule[] = [];
const unresolvedChannelIds: ChannelId[] = [];
for (const channelId of channelIds) {

View File

@@ -14,6 +14,20 @@ function getPathValue(root: Record<string, unknown>, path: string[]): unknown {
return cursor;
}
function collectExplicitRuleOwnedChannelIds(
extraRules: readonly LegacyConfigRule[],
): ReadonlySet<string> | undefined {
const channelIds = new Set<string>();
for (const rule of extraRules) {
const [first, second] = rule.path;
if (first !== "channels" || typeof second !== "string" || second === "defaults") {
continue;
}
channelIds.add(second);
}
return channelIds.size > 0 ? channelIds : undefined;
}
export function findLegacyConfigIssues(
raw: unknown,
sourceRaw?: unknown,
@@ -27,9 +41,10 @@ export function findLegacyConfigIssues(
const sourceRoot =
sourceRaw && typeof sourceRaw === "object" ? (sourceRaw as Record<string, unknown>) : root;
const issues: LegacyConfigIssue[] = [];
const explicitRuleOwnedChannelIds = collectExplicitRuleOwnedChannelIds(extraRules);
for (const rule of [
...LEGACY_CONFIG_RULES,
...collectChannelLegacyConfigRules(raw, touchedPaths),
...collectChannelLegacyConfigRules(raw, touchedPaths, explicitRuleOwnedChannelIds),
...extraRules,
]) {
const cursor = getPathValue(root, rule.path);