perf: skip unchanged live snapshot sections (#285)
CI / lint (pull_request) Successful in 25s
CI / build-frontend (pull_request) Successful in 5s

This commit is contained in:
timmy committed 2026-08-08 09:35:48 +00:00
1 parent e28472b268
commit fedddb246d
10 files changed
+188 -20

No files matched your search

+10 -3
View File
@@ -10,6 +10,8 @@ function createContextPoller({
let inFlight = null;
let timer = null;
let stopped = false;
let revisions = {};
let retainedSnapshot = null;
function cancelTimer() {
if (timer !== null) clearTimer(timer);
@@ -31,14 +33,19 @@ function createContextPoller({
let request;
try {
request = fetchContext();
request = fetchContext({ ...revisions });
} catch (error) {
request = Promise.reject(error);
}
inFlight = Promise.resolve(request)
.then((snapshot) => {
onSnapshot(snapshot);
return snapshot;
const changedSections = ['context', 'events', 'notifications'].filter(
(section) => Object.prototype.hasOwnProperty.call(snapshot, section)
);
retainedSnapshot = retainedSnapshot ? { ...retainedSnapshot, ...snapshot } : { ...snapshot };
revisions = { ...revisions, ...(snapshot.revisions || {}) };
onSnapshot(retainedSnapshot, changedSections);
return retainedSnapshot;
})
.catch((error) => {
onError(error);
+18 -7
View File
@@ -1004,8 +1004,15 @@ textarea { resize: vertical; min-height: 120px; }
function setClock() { qs('#clock').textContent = fmt(new Date()); }
setClock(); setInterval(setClock, 1000);
async function fetchLiveSnapshot() {
const res = await fetch('api/v1/live', { headers: { Accept: 'application/json' } });
async function fetchLiveSnapshot(revisions = {}) {
const params = new URLSearchParams();
Object.entries(revisions).forEach(([section, revision]) => {
if (Number.isInteger(revision) && revision >= 0) params.set(section + '_revision', revision);
});
const query = params.toString();
const res = await fetch('api/v1/live' + (query ? '?' + query : ''), {
headers: { Accept: 'application/json' },
});
if (!res.ok) throw new Error('HTTP ' + res.status);
return res.json();
}
@@ -2445,15 +2452,19 @@ textarea { resize: vertical; min-height: 120px; }
qs('#gitea-events-status').textContent = message;
}
function renderLiveSnapshot(snapshot) {
function renderLiveSnapshot(snapshot, changedSections = ['context', 'events', 'notifications']) {
setOfflineWorkMode(false);
offlineStatus.hidden = true;
const contextFreshness = snapshot.freshness?.sections?.context;
const eventsFreshness = snapshot.freshness?.sections?.events;
const notificationFreshness = snapshot.freshness?.sections?.notifications;
const contextChanged = changedSections.includes('context');
const notificationsChanged = changedSections.includes('notifications');
const eventsChanged = changedSections.includes('events');
const workChanged = contextChanged || notificationsChanged;
const hasNotifications = Array.isArray(snapshot.notifications);
const notificationsFresh = hasNotifications && !notificationFreshness?.stale;
if (hasNotifications) {
if (notificationsChanged && hasNotifications) {
if (notificationPagination.page > 1) {
const byId = new Map(lastNotifications.map(item => [item.id, item]));
snapshot.notifications.forEach(item => byId.set(item.id, item));
@@ -2471,7 +2482,7 @@ textarea { resize: vertical; min-height: 120px; }
});
}
}
if (snapshot.context) {
if (snapshot.context && workChanged) {
setOfflineWorkMode(false);
const contextIdentityFresh = !snapshot.context.error && !contextFreshness?.stale &&
!contextFreshness?.degraded && !contextFreshness?.revalidating;
@@ -2494,8 +2505,8 @@ textarea { resize: vertical; min-height: 120px; }
}
flushIssueOutbox();
flushAuthoredOutbox();
} else handleContextError(new Error('Context section unavailable'));
if (Array.isArray(snapshot.events)) paintEventStream(snapshot.events);
} else if (!snapshot.context) handleContextError(new Error('Context section unavailable'));
if (eventsChanged && Array.isArray(snapshot.events)) paintEventStream(snapshot.events);
if (eventsFreshness?.revalidating) {
setEventStreamStatus('Refreshing activity · showing last activity');
} else if (eventsFreshness?.stale || eventsFreshness?.degraded) {
+1 -1
View File
@@ -1,6 +1,6 @@
const BASE = new URL('./', self.location.href).pathname;
importScripts(BASE + 'static/background-issue-sync.js');
const CACHE = 'stackchain-dashboard-shell-v22';
const CACHE = 'stackchain-dashboard-shell-v23';
const OUTAGE_STATUSES = new Set([500, 502, 503, 504]);
const SHELL = [
BASE,