Skip to content

Commit 86cf3f0

Browse files
authored
ENG-1574: Add dual-read console logs to setting setters (#914)
* ENG-1574: Add dual-read console logs to setting setters Log legacy and block prop values with match/mismatch status when a setting is changed. Fix broken import in storedRelations. * ENG-1574: Add init-time dual-read log and window.dgDualReadLog() Log all legacy vs block prop settings on init. Remove setter logging. Expose dgDualReadLog() on window for on-demand use. * ENG-1574: Fix eslint naming-convention warnings in init.ts * ENG-1574: Use deepEqual instead of JSON.stringify for comparison JSON.stringify is key-order dependent, causing false mismatches when legacy and block props return keys in different order. * ENG-1574: Remove dead code, use deepEqual for comparison * ENG-1574: Fix review feedback — try-catch, flag exclusion, type guard
1 parent 8830ade commit 86cf3f0

2 files changed

Lines changed: 95 additions & 2 deletions

File tree

apps/roam/src/components/settings/utils/accessors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import { PERSONAL_KEYS, QUERY_KEYS, GLOBAL_KEYS } from "./settingKeys";
4545
const isRecord = (value: unknown): value is Record<string, unknown> =>
4646
typeof value === "object" && value !== null && !Array.isArray(value);
4747

48-
const deepEqual = (a: unknown, b: unknown): boolean => {
48+
export const deepEqual = (a: unknown, b: unknown): boolean => {
4949
if (a === b) return true;
5050
const isEmpty = (v: unknown) =>
5151
v === undefined || v === null || v === "" || v === false;

apps/roam/src/components/settings/utils/init.ts

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,19 @@ import type { json } from "~/utils/getBlockProps";
77
import INITIAL_NODE_VALUES from "~/data/defaultDiscourseNodes";
88
import DEFAULT_RELATION_VALUES from "~/data/defaultDiscourseRelations";
99
import DEFAULT_RELATIONS_BLOCK_PROPS from "~/components/settings/data/defaultRelationsBlockProps";
10-
import { getAllDiscourseNodes } from "./accessors";
10+
import {
11+
getAllDiscourseNodes,
12+
isNewSettingsStoreEnabled,
13+
deepEqual,
14+
getFeatureFlags,
15+
getGlobalSettings,
16+
getPersonalSettings,
17+
getDiscourseNodeSettings,
18+
readAllLegacyFeatureFlags,
19+
readAllLegacyGlobalSettings,
20+
readAllLegacyPersonalSettings,
21+
readAllLegacyDiscourseNodeSettings,
22+
} from "./accessors";
1123
import {
1224
migrateGraphLevel,
1325
migratePersonalSettings,
@@ -324,10 +336,91 @@ export type InitSchemaResult = {
324336
nodePageUids: Record<string, string>;
325337
};
326338

339+
const logDualReadComparison = (): void => {
340+
if (!isNewSettingsStoreEnabled()) return;
341+
342+
const legacyFlags = readAllLegacyFeatureFlags();
343+
const blockFlags = getFeatureFlags();
344+
const omitStoreFlag = (
345+
flags: Record<string, unknown>,
346+
): Record<string, unknown> =>
347+
Object.fromEntries(
348+
Object.entries(flags).filter(([k]) => k !== "Use new settings store"),
349+
);
350+
const flagsMatch = deepEqual(
351+
omitStoreFlag(blockFlags),
352+
omitStoreFlag(legacyFlags),
353+
);
354+
355+
const legacyGlobal = readAllLegacyGlobalSettings();
356+
const blockGlobal = getGlobalSettings();
357+
const globalMatch = deepEqual(blockGlobal, legacyGlobal);
358+
359+
const legacyPersonal = readAllLegacyPersonalSettings();
360+
const blockPersonal = getPersonalSettings();
361+
const personalMatch = deepEqual(blockPersonal, legacyPersonal);
362+
363+
const nodes = getAllDiscourseNodes();
364+
const nodeResults: {
365+
name: string;
366+
match: boolean;
367+
legacy: unknown;
368+
blockProps: unknown;
369+
}[] = [];
370+
for (const node of nodes) {
371+
const legacy = readAllLegacyDiscourseNodeSettings(node.type, node.text);
372+
const blockProps = getDiscourseNodeSettings(node.type);
373+
nodeResults.push({
374+
name: node.text,
375+
match: deepEqual(blockProps, legacy),
376+
legacy,
377+
blockProps,
378+
});
379+
}
380+
381+
const mismatches = [
382+
!flagsMatch && "Feature Flags",
383+
!globalMatch && "Global",
384+
!personalMatch && "Personal",
385+
...nodeResults.filter((n) => !n.match).map((n) => n.name),
386+
].filter((x): x is string => Boolean(x));
387+
388+
const summary =
389+
mismatches.length === 0
390+
? "All settings match"
391+
: `(${mismatches.length}) Settings don't match: ${mismatches.join(", ")}`;
392+
393+
const nodeMap = (key: "legacy" | "blockProps") =>
394+
Object.fromEntries(nodeResults.map((n) => [n.name, n[key]]));
395+
396+
/* eslint-disable @typescript-eslint/naming-convention */
397+
console.log(`[DG Dual-Read] ${summary}`);
398+
console.log("[DG Dual-Read] Legacy:", {
399+
"Feature Flags": legacyFlags,
400+
Global: legacyGlobal,
401+
Personal: legacyPersonal,
402+
...nodeMap("legacy"),
403+
});
404+
console.log("[DG Dual-Read] Block props:", {
405+
"Feature Flags": blockFlags,
406+
Global: blockGlobal,
407+
Personal: blockPersonal,
408+
...nodeMap("blockProps"),
409+
});
410+
/* eslint-enable @typescript-eslint/naming-convention */
411+
};
412+
327413
export const initSchema = async (): Promise<InitSchemaResult> => {
328414
const blockUids = await initSettingsPageBlocks();
329415
await migrateGraphLevel(blockUids);
330416
const nodePageUids = await initDiscourseNodePages();
331417
await migratePersonalSettings(blockUids);
418+
try {
419+
logDualReadComparison();
420+
} catch (e) {
421+
console.warn("[DG Dual-Read] Comparison failed:", e);
422+
}
423+
(window as unknown as Record<string, unknown>).dgDualReadLog =
424+
logDualReadComparison;
332425
return { blockUids, nodePageUids };
333426
};

0 commit comments

Comments
 (0)