feat: lazy loading sessions (faster page load)

This commit is contained in:
Oliver Kieselbach
2026-04-15 00:08:56 +02:00
parent 01e29da0f2
commit 9b2f801530
5 changed files with 42 additions and 12 deletions
@@ -39,6 +39,11 @@ namespace AutopilotMonitor.Functions.Functions.Sessions
if (!string.IsNullOrEmpty(daysParam) && int.TryParse(daysParam, out var parsedDays) && parsedDays > 0)
days = parsedDays;
var limitParam = query["limit"];
int limit = 100;
if (!string.IsNullOrEmpty(limitParam) && int.TryParse(limitParam, out var parsedLimit))
limit = Math.Clamp(parsedLimit, 1, 100);
SessionPage page;
if (!string.IsNullOrEmpty(tenantIdFilter))
@@ -50,13 +55,13 @@ namespace AutopilotMonitor.Functions.Functions.Sessions
return badRequest;
}
_logger.LogInformation("Fetching sessions for tenant {TenantId} (User: {UserEmail}, cursor: {Cursor}, days: {Days})", tenantIdFilter, userEmail, cursor ?? "none", days?.ToString() ?? "all");
page = await _sessionRepo.GetSessionsAsync(tenantIdFilter, maxResults: 100, cursor: cursor, days: days);
_logger.LogInformation("Fetching sessions for tenant {TenantId} (User: {UserEmail}, cursor: {Cursor}, days: {Days}, limit: {Limit})", tenantIdFilter, userEmail, cursor ?? "none", days?.ToString() ?? "all", limit);
page = await _sessionRepo.GetSessionsAsync(tenantIdFilter, maxResults: limit, cursor: cursor, days: days);
}
else
{
_logger.LogInformation("Fetching all sessions across all tenants (User: {UserEmail}, cursor: {Cursor}, days: {Days})", userEmail, cursor ?? "none", days?.ToString() ?? "all");
page = await _sessionRepo.GetAllSessionsAsync(maxResults: 100, cursor: cursor, days: days);
_logger.LogInformation("Fetching all sessions across all tenants (User: {UserEmail}, cursor: {Cursor}, days: {Days}, limit: {Limit})", userEmail, cursor ?? "none", days?.ToString() ?? "all", limit);
page = await _sessionRepo.GetAllSessionsAsync(maxResults: limit, cursor: cursor, days: days);
}
return await req.OkAsync(new
@@ -35,9 +35,14 @@ namespace AutopilotMonitor.Functions.Functions.Sessions
if (!string.IsNullOrEmpty(daysParam) && int.TryParse(daysParam, out var parsedDays) && parsedDays > 0)
days = parsedDays;
_logger.LogInformation("Fetching sessions for tenant {TenantId} (cursor: {Cursor}, days: {Days})", tenantId, cursor ?? "none", days?.ToString() ?? "all");
var limitParam = query["limit"];
int limit = 100;
if (!string.IsNullOrEmpty(limitParam) && int.TryParse(limitParam, out var parsedLimit))
limit = Math.Clamp(parsedLimit, 1, 100);
var page = await _sessionRepo.GetSessionsAsync(tenantId, maxResults: 100, cursor: cursor, days: days);
_logger.LogInformation("Fetching sessions for tenant {TenantId} (cursor: {Cursor}, days: {Days}, limit: {Limit})", tenantId, cursor ?? "none", days?.ToString() ?? "all", limit);
var page = await _sessionRepo.GetSessionsAsync(tenantId, maxResults: limit, cursor: cursor, days: days);
return await req.OkAsync(new
{
@@ -146,13 +146,22 @@ export function useDashboardSessions({
}
}, [getAccessToken, addNotification, setBlockedDevicesSet]);
const getInitialLimit = (): number | undefined => {
if (typeof window === "undefined") return undefined;
const stored = window.localStorage.getItem("sessionsPerPage");
const parsed = stored ? parseInt(stored, 10) : NaN;
const value = Number.isFinite(parsed) && parsed > 0 ? parsed : 10;
return Math.min(value, 100);
};
const fetchSessions = useCallback(async (loadMoreCursor?: string, globalTenantIdOverride?: string) => {
try {
const rawFilter = globalTenantIdOverride !== undefined ? globalTenantIdOverride : tenantIdFilterRef.current.trim();
const effectiveTenantFilter = asGuidOrUndefined(rawFilter);
const initialLimit = loadMoreCursor ? undefined : getInitialLimit();
let endpoint = globalAdminModeRef.current
? api.globalSessions.list(effectiveTenantFilter)
: api.sessions.list(tenantIdRef.current ?? undefined);
? api.globalSessions.list(effectiveTenantFilter, undefined, initialLimit)
: api.sessions.list(tenantIdRef.current ?? undefined, undefined, initialLimit);
if (loadMoreCursor) {
endpoint += endpoint.includes("?") ? "&" : "?";
@@ -91,6 +91,17 @@ export default function Home() {
if (!globalAdminMode) setTenantIdFilter("");
}, [globalAdminMode]);
// Auto-load more when the user needs more sessions than currently loaded
// (e.g. increased sessionsPerPage, paginated forward, or applied a sort/column filter
// that would benefit from the full dataset). Cheap server roundtrip, paid only on demand.
useEffect(() => {
if (loading || loadingMore || !hasMore) return;
const needed = currentPage * sessionsPerPage;
if (sessions.length < needed) {
loadMore();
}
}, [sessions.length, currentPage, sessionsPerPage, hasMore, loading, loadingMore, loadMore]);
const applyTenantIdFilter = (value: string) => {
setTenantIdFilter(value);
};
+4 -4
View File
@@ -21,8 +21,8 @@ export const api = {
// ── Sessions ──────────────────────────────────────────────────────────────
sessions: {
list: (tenantId?: string, days?: number) =>
`${API_BASE_URL}/api/sessions${qs({ tenantId, days: days?.toString() })}`,
list: (tenantId?: string, days?: number, limit?: number) =>
`${API_BASE_URL}/api/sessions${qs({ tenantId, days: days?.toString(), limit: limit?.toString() })}`,
get: (sessionId: string, tenantId?: string) =>
`${API_BASE_URL}/api/sessions/${sessionId}${qs({ tenantId })}`,
events: (sessionId: string, tenantId?: string) =>
@@ -45,8 +45,8 @@ export const api = {
// ── Global Sessions (global admin) ────────────────────────────────────────
globalSessions: {
list: (tenantId?: string, days?: number) =>
`${API_BASE_URL}/api/global/sessions${qs({ tenantId, days: days?.toString() })}`,
list: (tenantId?: string, days?: number, limit?: number) =>
`${API_BASE_URL}/api/global/sessions${qs({ tenantId, days: days?.toString(), limit: limit?.toString() })}`,
},
// ── Config ────────────────────────────────────────────────────────────────