mirror of
https://github.com/tale/headplane.git
synced 2026-08-27 15:37:04 +00:00
perf: switch to SSE dispatched changes
Previously we would use naive revalidators which would invalidate EVERY SINGLE action loader every 3 seconds, resulting in several fetches. It would also bubble fetches across the layout actions into the individual pages. This new approach selectively has live stores of resources which then poll for changes on the server side and then dispatches updates to the client via a new /events/live SSE endpoint.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { createHash } from "node:crypto";
|
||||
|
||||
import PageError from "~/components/page-error";
|
||||
import { nodesResource, usersResource } from "~/server/headscale/live-store";
|
||||
import { Capabilities, Roles } from "~/server/web/roles";
|
||||
import type { Role } from "~/server/web/roles";
|
||||
import type { Machine, User } from "~/types";
|
||||
@@ -55,7 +56,12 @@ export async function loader({ request, context }: Route.LoaderArgs) {
|
||||
try {
|
||||
const apiKey = context.auth.getHeadscaleApiKey(principal, context.oidc?.apiKey);
|
||||
const api = context.hsApi.getRuntimeClient(apiKey);
|
||||
[nodes, apiUsers] = await Promise.all([api.getNodes(), api.getUsers()]);
|
||||
const [nodesSnap, usersSnap] = await Promise.all([
|
||||
context.hsLive.get(nodesResource, api),
|
||||
context.hsLive.get(usersResource, api),
|
||||
]);
|
||||
nodes = nodesSnap.data;
|
||||
apiUsers = usersSnap.data;
|
||||
} catch (error) {
|
||||
log.warn("api", "Failed to fetch Headscale API data: %s", String(error));
|
||||
apiError =
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { data } from "react-router";
|
||||
|
||||
import { usersResource } from "~/server/headscale/live-store";
|
||||
import { getOidcSubject } from "~/server/web/headscale-identity";
|
||||
import { Capabilities } from "~/server/web/roles";
|
||||
import type { Role } from "~/server/web/roles";
|
||||
@@ -38,6 +39,7 @@ export async function userAction({ request, context }: Route.ActionArgs) {
|
||||
}
|
||||
|
||||
await api.createUser(name, email, displayName);
|
||||
await context.hsLive.refresh(usersResource, api);
|
||||
return { message: "User created successfully" };
|
||||
}
|
||||
case "delete_user": {
|
||||
@@ -49,6 +51,7 @@ export async function userAction({ request, context }: Route.ActionArgs) {
|
||||
}
|
||||
|
||||
await api.deleteUser(userId);
|
||||
await context.hsLive.refresh(usersResource, api);
|
||||
return { message: "User deleted successfully" };
|
||||
}
|
||||
case "rename_user": {
|
||||
@@ -72,6 +75,7 @@ export async function userAction({ request, context }: Route.ActionArgs) {
|
||||
}
|
||||
|
||||
await api.renameUser(userId, newName);
|
||||
await context.hsLive.refresh(usersResource, api);
|
||||
return { message: "User renamed successfully" };
|
||||
}
|
||||
case "reassign_user": {
|
||||
|
||||
Reference in New Issue
Block a user