Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

76 changes: 50 additions & 26 deletions src/store.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/***FILE_CONTENT_START***/
/**
* NexusFlow Gatekeeper - State Store
*
Expand Down Expand Up @@ -43,7 +42,7 @@ interface NexusStore {
// State
nodes: RoboticNode[];
pendingMessages: Map<string, PendingMessage>;
appliedMessageIds: Set<string>;
appliedMessageIds: Map<string, number>; // Maps ID to timestamp

// Actions
setNodeState: (nodeId: string, state: NodeState) => void;
Expand Down Expand Up @@ -119,7 +118,7 @@ export const useNexusStore = create<NexusStore>()(
// Initial State
nodes: initialNodes,
pendingMessages: new Map(),
appliedMessageIds: new Set(),
appliedMessageIds: new Map(),
metrics: {
messagesSent: 0,
messagesReceived: 0,
Expand Down Expand Up @@ -208,22 +207,30 @@ export const useNexusStore = create<NexusStore>()(
switch (type) {
case 'NODE_STATE_CHANGE': {
const { nodeId, state } = payload as { nodeId: string; state: NodeState };
set((store) => ({
nodes: store.nodes.map((n) =>
n.id === nodeId ? { ...n, state } : n
),
appliedMessageIds: new Set([...store.appliedMessageIds, id]),
}));
set((store) => {
const newApplied = new Map(store.appliedMessageIds);
newApplied.set(id, Date.now());
return {
nodes: store.nodes.map((n) =>
n.id === nodeId ? { ...n, state } : n
),
appliedMessageIds: newApplied,
};
});
logger.debug({ nodeId, state }, 'Applied state change');
return true;
}

case 'STATE_SYNC': {
const nodes = payload as RoboticNode[];
set((store) => ({
nodes,
appliedMessageIds: new Set([...store.appliedMessageIds, id]),
}));
set((store) => {
const newApplied = new Map(store.appliedMessageIds);
newApplied.set(id, Date.now());
return {
nodes,
appliedMessageIds: newApplied,
};
});
logger.debug({ nodeCount: nodes.length }, 'Applied state sync');
return true;
}
Expand Down Expand Up @@ -272,9 +279,13 @@ export const useNexusStore = create<NexusStore>()(
* Mark message as locally applied
*/
markMessageApplied: (messageId) => {
set((store) => ({
appliedMessageIds: new Set([...store.appliedMessageIds, messageId]),
}));
set((store) => {
const newApplied = new Map(store.appliedMessageIds);
newApplied.set(messageId, Date.now());
return {
appliedMessageIds: newApplied,
};
});
},

/**
Expand Down Expand Up @@ -342,7 +353,7 @@ export const useNexusStore = create<NexusStore>()(
const { pendingMessages, appliedMessageIds } = get();
const now = Date.now();
const newPendingMessages = new Map<string, PendingMessage>();
const newAppliedIds = new Set<string>();
const newAppliedIds = new Map<string, number>();
let cleanedCount = 0;

pendingMessages.forEach((pending, messageId) => {
Expand All @@ -363,12 +374,10 @@ export const useNexusStore = create<NexusStore>()(

// Clean up old applied IDs
let cleanedAppliedCount = 0;
appliedMessageIds.forEach((id) => {
// UUID v4 format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
const timestampPart = id.substring(0, 8);
const timestamp = parseInt(timestampPart, 16) * 4294966.296; // Approximate conversion
if (now - timestamp < CLEANUP_DELAY_MS * 1000) {
newAppliedIds.add(id);
appliedMessageIds.forEach((timestamp, id) => {
// Use actual stored timestamp instead of parsing UUID
if (now - timestamp < CLEANUP_DELAY_MS) {
newAppliedIds.set(id, timestamp);
} else {
cleanedAppliedCount++;
}
Expand Down Expand Up @@ -399,7 +408,8 @@ export const useNexusStore = create<NexusStore>()(
if (!persistedState) return currentState;

const converted: NexusStore = { ...currentState } as NexusStore;
const psAny = persistedState as Partial<NexusStore>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const psAny = persistedState as any;

if (psAny.pendingMessages) {
const map = new Map<string, PendingMessage>();
Expand All @@ -410,7 +420,22 @@ export const useNexusStore = create<NexusStore>()(
}

if (psAny.appliedMessageIds) {
converted.appliedMessageIds = new Set<string>(psAny.appliedMessageIds as unknown as string[]);
const map = new Map<string, number>();

if (Array.isArray(psAny.appliedMessageIds)) {
// Legacy format or array serialization: assume current time for lack of better data
psAny.appliedMessageIds.forEach((id: string) => map.set(id, Date.now()));
} else if (typeof psAny.appliedMessageIds === 'object') {
// Object format: key -> timestamp
Object.entries(psAny.appliedMessageIds).forEach(([key, value]) => {
if (typeof value === 'number') {
map.set(key, value);
} else {
map.set(key, Date.now());
}
});
}
converted.appliedMessageIds = map;
}

return converted;
Expand Down Expand Up @@ -519,4 +544,3 @@ export const robotAlphaPath: { x: number; y: number }[] = [
{ x: 200, y: 100 },
{ x: 150, y: 100 },
];
/***FILE_CONTENT_END***/
Loading