UCI Troubleshooting Tests
Console Tests
The following tests can be executed in the developer tools console to inspect and troubleshoot the UCI Cache Buster
List out the current versions in the cache
(async () => {
const solution = "SenseiControlsV1";
const controls = ["IQ.AltusAssist", "IQ.AltusDashboard", "IQ.GridCellRenderer"];
const targets = ["https://uci-state/", "WebResources"];
// Match the app's frame resolution: look up at most two levels for Dynamics.
const dynamicsWindow = (() => {
try {
let candidate = window;
if (candidate.__preload == null) candidate = candidate.parent;
if (candidate.__preload == null) candidate = candidate.parent;
return candidate.__preload == null ? window : candidate;
} catch {
return window;
}
})();
const cacheStorage = dynamicsWindow.caches;
const existing = cacheStorage ? await cacheStorage.keys() : [];
const deployed = dynamicsWindow.SenseiIqTelemetryProperties?.SolutionVersions
?.find(v => String(v.solutionName).toLowerCase() === solution.toLowerCase())?.version;
let sentinel;
try {
sentinel = JSON.parse(dynamicsWindow.sessionStorage.getItem("altus.uciCacheBust") || "null");
} catch (e) {
sentinel = `unreadable: ${e.name}`;
}
let serviceWorkerCount;
try {
serviceWorkerCount = (
await dynamicsWindow.navigator?.serviceWorker?.getRegistrations?.() || []
).length;
} catch (e) {
serviceWorkerCount = `unavailable: ${e.name}`;
}
const cacheEntryCounts = {};
for (const name of targets) {
cacheEntryCounts[name] = !cacheStorage
? "unavailable"
: existing.includes(name)
? (await (await cacheStorage.open(name)).keys()).length
: "missing";
}
const rows = [];
const findControl = name =>
controls.find(control =>
String(name || "").toLowerCase().includes(control.toLowerCase())
);
const add = (control, kind, name, cached) => {
if (typeof cached === "string" && cached) {
rows.push({
control,
kind,
name,
cached,
deployed: deployed || "missing",
stale: deployed ? cached !== deployed : "unknown"
});
}
};
if (cacheStorage && existing.includes(targets[0])) {
const cache = await cacheStorage.open(targets[0]);
const [request] = await cache.keys();
const response = request ? await cache.match(request) : null;
const state = response ? await response.json() : {};
for (const resource of Object.values(state?.metadata?.webResources || {})) {
const control = findControl(resource?.name);
if (
control &&
String(resource?.solutionName || "").toLowerCase() === solution.toLowerCase()
) {
add(control, "resource", resource.name, resource.solutionVersion);
}
}
for (const manifest of Object.values(state?.metadata?.controlManifests || {})) {
const control = findControl(manifest?.ConstructorName);
if (
control &&
String(manifest?.SolutionName || "").toLowerCase() === solution.toLowerCase()
) {
add(control, "manifest", manifest.ConstructorName, manifest.SolutionVersion);
}
}
}
for (const control of controls) {
if (!rows.some(row => row.control === control)) {
rows.push({
control,
kind: "not cached",
name: "No matching entry in uci-state",
cached: "missing",
deployed: deployed || "missing",
stale: "unknown"
});
}
}
console.log({
at: new Date().toISOString(),
inspectedWindowIsCurrent: dynamicsWindow === window,
cacheStorageAvailable: !!cacheStorage,
serviceWorkerCount,
cacheEntryCounts,
deployedVersion: deployed || "missing",
sentinel
});
console.table(rows);
})().catch(console.error);
Stale cache example:

Fresh cache example:

Create a UCI Cache Issue
(async () => {
const CONTROL = "IQ.AltusDashboard";
const SOLUTION = "SenseiControlsV1";
const CORRUPTED_VERSION = "0.0.0.0";
const SENTINEL = "altus.uciCacheBust";
const cache = await caches.open("https://uci-state/");
const requests = await cache.keys();
if (requests.length === 0) throw new Error("No uci-state entry found.");
const request = requests[0];
const response = await cache.match(request);
if (!response) throw new Error("Unable to read uci-state entry.");
const state = JSON.parse(await response.text());
let changed = 0;
const isTargetSolution = (value) =>
typeof value === "string" && value.toLowerCase() === SOLUTION.toLowerCase();
for (const resource of Object.values(state.metadata?.webResources ?? {})) {
if (
resource?.name?.startsWith(`cc_${CONTROL}/`) &&
isTargetSolution(resource.solutionName)
) {
resource.solutionVersion = CORRUPTED_VERSION;
changed++;
}
}
for (const manifest of Object.values(
state.metadata?.controlManifests ?? {},
)) {
if (
manifest?.ConstructorName === CONTROL &&
isTargetSolution(manifest.SolutionName)
) {
manifest.SolutionVersion = CORRUPTED_VERSION;
changed++;
}
}
if (changed === 0) {
throw new Error(`No cached entries found for ${CONTROL}.`);
}
await cache.put(
request,
new Response(JSON.stringify(state), {
headers: { "Content-Type": "application/json" },
}),
);
sessionStorage.removeItem(SENTINEL);
console.table({
control: CONTROL,
corruptedEntries: changed,
corruptedVersion: CORRUPTED_VERSION,
stateEntry: request.url,
});
location.reload();
})().catch(console.error);
Cleanup after testing
(async () => {
await caches.delete("https://uci-state/");
await caches.delete("WebResources");
sessionStorage.removeItem("altus.uciCacheBust");
location.reload();
})();