feat: migrate to real Zustand store (Phase 2)

This commit is contained in:
Mohamed Boudra
2025-12-02 09:55:59 +00:00
parent b278b43fac
commit fa1d7dd295
4 changed files with 164 additions and 202 deletions

View File

@@ -1,9 +1,9 @@
import { useSyncExternalStore } from "react";
import { create } from "zustand";
import { subscribeWithSelector } from "zustand/middleware";
import type { SessionContextValue } from "@/contexts/session-context";
import type { AgentDirectoryEntry } from "@/types/agent-directory";
import { isPerfLoggingEnabled, measurePayload, perfLog } from "@/utils/perf";
// SessionData mirrors SessionContextValue so consumers can subscribe to a single source of truth.
export type SessionData = SessionContextValue;
interface SessionStoreState {
@@ -21,24 +21,14 @@ interface SessionStore extends SessionStoreState {
getAgentDirectory: (serverId: string) => AgentDirectoryEntry[] | undefined;
}
type SessionListener = () => void;
let storeState: SessionStoreState = { sessions: {}, agentDirectory: {} };
const listeners = new Set<SessionListener>();
const SESSION_STORE_LOG_TAG = "[SessionStore]";
let sessionStoreUpdateCount = 0;
const emit = () => {
for (const listener of listeners) {
listener();
}
};
const logSessionStoreUpdate = (
function logSessionStoreUpdate(
type: "setSession" | "updateSession" | "clearSession" | "setAgentDirectory" | "clearAgentDirectory",
serverId: string,
payload?: unknown
) => {
) {
if (!isPerfLoggingEnabled()) {
return;
}
@@ -52,128 +42,7 @@ const logSessionStoreUpdate = (
payloadFieldCount: metrics?.fieldCount ?? 0,
timestamp: Date.now(),
});
};
const updateStoreState = (updater: (prev: SessionStoreState) => SessionStoreState) => {
const next = updater(storeState);
if (next === storeState) {
return;
}
storeState = next;
emit();
};
const setSession: SessionStore["setSession"] = (serverId, data) => {
updateStoreState((prev) => {
if (prev.sessions[serverId] === data) {
return prev;
}
logSessionStoreUpdate("setSession", serverId, data);
return {
...prev,
sessions: {
...prev.sessions,
[serverId]: data,
},
};
});
};
const updateSession: SessionStore["updateSession"] = (serverId, partial) => {
updateStoreState((prev) => {
const existing = prev.sessions[serverId];
const next: SessionData | undefined = existing
? { ...existing, ...partial, serverId }
: partial.serverId
? ({ ...(partial as SessionData), serverId })
: undefined;
if (!next) {
return prev;
}
if (existing && shallowEqual(existing, next)) {
return prev;
}
logSessionStoreUpdate("updateSession", serverId, partial);
return {
...prev,
sessions: {
...prev.sessions,
[serverId]: next,
},
};
});
};
const clearSession: SessionStore["clearSession"] = (serverId) => {
updateStoreState((prev) => {
if (!(serverId in prev.sessions)) {
return prev;
}
logSessionStoreUpdate("clearSession", serverId);
const nextSessions = { ...prev.sessions };
delete nextSessions[serverId];
return { ...prev, sessions: nextSessions };
});
};
const getSession: SessionStore["getSession"] = (serverId) => {
return storeState.sessions[serverId];
};
const setAgentDirectory: SessionStore["setAgentDirectory"] = (serverId, agents) => {
updateStoreState((prev) => {
const existing = prev.agentDirectory[serverId];
if (existing && areAgentDirectoriesEqual(existing, agents)) {
return prev;
}
logSessionStoreUpdate("setAgentDirectory", serverId, { agentCount: agents.length });
return {
...prev,
agentDirectory: {
...prev.agentDirectory,
[serverId]: agents,
},
};
});
};
const clearAgentDirectory: SessionStore["clearAgentDirectory"] = (serverId) => {
updateStoreState((prev) => {
if (!(serverId in prev.agentDirectory)) {
return prev;
}
logSessionStoreUpdate("clearAgentDirectory", serverId);
const nextDirectory = { ...prev.agentDirectory };
delete nextDirectory[serverId];
return { ...prev, agentDirectory: nextDirectory };
});
};
const getAgentDirectory: SessionStore["getAgentDirectory"] = (serverId) => {
return storeState.agentDirectory[serverId];
};
const subscribe = (listener: SessionListener) => {
listeners.add(listener);
return () => {
listeners.delete(listener);
};
};
const buildSnapshot = (): SessionStore => ({
sessions: storeState.sessions,
agentDirectory: storeState.agentDirectory,
setSession,
updateSession,
clearSession,
getSession,
setAgentDirectory,
clearAgentDirectory,
getAgentDirectory,
});
}
const shallowEqual = (left: SessionData, right: SessionData): boolean => {
if (left === right) {
@@ -192,40 +61,116 @@ const shallowEqual = (left: SessionData, right: SessionData): boolean => {
return true;
};
export function useSessionStore<T>(selector: (state: SessionStore) => T): T {
return useSyncExternalStore(
subscribe,
() => selector(buildSnapshot()),
() => selector(buildSnapshot())
);
}
function areAgentDirectoriesEqual(
left: AgentDirectoryEntry[] | undefined,
right: AgentDirectoryEntry[]
): boolean {
function areAgentDirectoriesEqual(left: AgentDirectoryEntry[] | undefined, right: AgentDirectoryEntry[]): boolean {
if (!left) {
return false;
}
if (left.length !== right.length) {
return false;
}
const leftById = new Map(left.map((entry) => [entry.id, entry]));
for (const entry of right) {
const previous = leftById.get(entry.id);
if (!previous) {
return left.every((entry, index) => {
const other = right[index];
if (!other) {
return false;
}
if (
previous.serverId !== entry.serverId ||
previous.title !== entry.title ||
previous.status !== entry.status ||
previous.provider !== entry.provider ||
previous.cwd !== entry.cwd ||
previous.lastActivityAt.getTime() !== entry.lastActivityAt.getTime()
) {
return false;
}
}
return true;
return (
entry.id === other.id &&
entry.status === other.status &&
entry.serverId === other.serverId &&
entry.lastActivityAt.getTime() === other.lastActivityAt.getTime()
);
});
}
export const useSessionStore = create<SessionStore>()(
subscribeWithSelector((set, get) => ({
sessions: {},
agentDirectory: {},
setSession: (serverId, data) => {
set((prev) => {
if (prev.sessions[serverId] === data) {
return prev;
}
logSessionStoreUpdate("setSession", serverId, data);
return {
...prev,
sessions: {
...prev.sessions,
[serverId]: data,
},
};
});
},
updateSession: (serverId, partial) => {
set((prev) => {
const existing = prev.sessions[serverId];
const next: SessionData | undefined = existing
? { ...existing, ...partial, serverId }
: partial.serverId
? ({ ...(partial as SessionData), serverId })
: undefined;
if (!next) {
return prev;
}
if (existing && shallowEqual(existing, next)) {
return prev;
}
logSessionStoreUpdate("updateSession", serverId, partial);
return {
...prev,
sessions: {
...prev.sessions,
[serverId]: next,
},
};
});
},
clearSession: (serverId) => {
set((prev) => {
if (!(serverId in prev.sessions)) {
return prev;
}
logSessionStoreUpdate("clearSession", serverId);
const nextSessions = { ...prev.sessions };
delete nextSessions[serverId];
return { ...prev, sessions: nextSessions };
});
},
getSession: (serverId) => {
return get().sessions[serverId];
},
setAgentDirectory: (serverId, agents) => {
set((prev) => {
const existing = prev.agentDirectory[serverId];
if (existing && areAgentDirectoriesEqual(existing, agents)) {
return prev;
}
logSessionStoreUpdate("setAgentDirectory", serverId, { agentCount: agents.length });
return {
...prev,
agentDirectory: {
...prev.agentDirectory,
[serverId]: agents,
},
};
});
},
clearAgentDirectory: (serverId) => {
set((prev) => {
if (!(serverId in prev.agentDirectory)) {
return prev;
}
logSessionStoreUpdate("clearAgentDirectory", serverId);
const nextDirectory = { ...prev.agentDirectory };
delete nextDirectory[serverId];
return { ...prev, agentDirectory: nextDirectory };
});
},
getAgentDirectory: (serverId) => {
return get().agentDirectory[serverId];
},
}))
);