Browse Source

Only persist on featureFlag

pull/780/head
philon- 11 months ago
parent
commit
1ceefc4676
  1. 2
      packages/web/src/App.tsx
  2. 194
      packages/web/src/core/stores/nodeDBStore/index.ts
  3. 3
      packages/web/src/index.tsx

2
packages/web/src/App.tsx

@ -12,8 +12,6 @@ import { Outlet } from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"; import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
import { ErrorBoundary } from "react-error-boundary"; import { ErrorBoundary } from "react-error-boundary";
import { MapProvider } from "react-map-gl/maplibre"; import { MapProvider } from "react-map-gl/maplibre";
// Import feature flags and dev overrides
import "@core/services/dev-overrides.ts";
export function App() { export function App() {
const { getDevice } = useDeviceStore(); const { getDevice } = useDeviceStore();

194
packages/web/src/core/stores/nodeDBStore/index.ts

@ -1,13 +1,13 @@
import { create } from "@bufbuild/protobuf"; import { create } from "@bufbuild/protobuf";
import { featureFlags } from "@core/services/featureFlags";
import { createStorage } from "@core/stores/utils/indexDB.ts"; import { createStorage } from "@core/stores/utils/indexDB.ts";
import { Protobuf, type Types } from "@meshtastic/core"; import { Protobuf, type Types } from "@meshtastic/core";
import { produce } from "immer"; import { produce } from "immer";
import { create as createStore } from "zustand"; import { create as createStore, type StateCreator } from "zustand";
import { persist } from "zustand/middleware"; import { type PersistOptions, persist } from "zustand/middleware";
import type { NodeError, NodeErrorType, ProcessPacketParams } from "./types"; import type { NodeError, NodeErrorType, ProcessPacketParams } from "./types";
const CURRENT_STORE_VERSION = 0; const CURRENT_STORE_VERSION = 0;
const NODEDB_RETENTION_NUM = 10; const NODEDB_RETENTION_NUM = 10;
export interface NodeDB { export interface NodeDB {
@ -334,95 +334,107 @@ function nodeDBFactory(
}; };
} }
export const useNodeDBStore = createStore<PrivateNodeDBState>()( export const nodeDBInitializer: StateCreator<PrivateNodeDBState> = (
persist( set,
(set, get) => ({ get,
nodeDBs: new Map(), ) => ({
nodeDBs: new Map(),
addNodeDB: (id) => {
const existing = get().nodeDBs.get(id); addNodeDB: (id) => {
if (existing) { const existing = get().nodeDBs.get(id);
return existing; if (existing) {
return existing;
}
const nodeDB = nodeDBFactory(id, get, set);
set(
produce<PrivateNodeDBState>((draft) => {
draft.nodeDBs.set(id, nodeDB);
// If over limit, remove oldest inserted. FIFO
if (draft.nodeDBs.size > NODEDB_RETENTION_NUM) {
const firstKey = draft.nodeDBs.keys().next().value;
if (firstKey !== undefined) {
draft.nodeDBs.delete(firstKey);
}
} }
const nodeDB = nodeDBFactory(id, get, set);
set(
produce<PrivateNodeDBState>((draft) => {
draft.nodeDBs.set(id, nodeDB);
// If over limit, remove oldest inserted. FIFO
if (draft.nodeDBs.size > NODEDB_RETENTION_NUM) {
const firstKey = draft.nodeDBs.keys().next().value;
if (firstKey !== undefined) {
draft.nodeDBs.delete(firstKey);
}
}
}),
);
return nodeDB;
},
removeNodeDB: (id) => {
set(
produce<PrivateNodeDBState>((draft) => {
draft.nodeDBs.delete(id);
}),
);
},
getNodeDBs: () => Array.from(get().nodeDBs.values()),
getNodeDB: (id) => get().nodeDBs.get(id),
}),
{
name: "meshtastic-nodedb-store",
storage: createStorage<NodeDBPersisted>(),
version: CURRENT_STORE_VERSION,
partialize: (s): NodeDBPersisted => ({
nodeDBs: new Map(
Array.from(s.nodeDBs.entries()).map(([id, db]) => [
id,
{
id: db.id,
myNodeNum: db.myNodeNum,
nodeMap: db.nodeMap,
nodeErrors: db.nodeErrors,
},
]),
),
}), }),
onRehydrateStorage: () => (state) => { );
if (!state) {
return; return nodeDB;
},
removeNodeDB: (id) => {
set(
produce<PrivateNodeDBState>((draft) => {
draft.nodeDBs.delete(id);
}),
);
},
getNodeDBs: () => Array.from(get().nodeDBs.values()),
getNodeDB: (id) => get().nodeDBs.get(id),
});
const persistOptions: PersistOptions<PrivateNodeDBState, NodeDBPersisted> = {
name: "meshtastic-nodedb-store",
storage: createStorage<NodeDBPersisted>(),
version: CURRENT_STORE_VERSION,
partialize: (s): NodeDBPersisted => ({
nodeDBs: new Map(
Array.from(s.nodeDBs.entries()).map(([id, db]) => [
id,
{
id: db.id,
myNodeNum: db.myNodeNum,
nodeMap: db.nodeMap,
nodeErrors: db.nodeErrors,
},
]),
),
}),
onRehydrateStorage: () => (state) => {
if (!state) {
return;
}
console.debug(
"NodeDBStore: Rehydrating state with ",
state.nodeDBs.size,
" nodeDBs -",
state.nodeDBs,
);
useNodeDBStore.setState(
produce<PrivateNodeDBState>((draft) => {
const rebuilt = new Map<number, NodeDB>();
for (const [id, data] of (
draft.nodeDBs as unknown as Map<number, NodeDBData>
).entries()) {
if (data.myNodeNum !== undefined) {
// Only rebuild if there is a nodenum set otherwise orphan dbs will acumulate
rebuilt.set(
id,
nodeDBFactory(
id,
useNodeDBStore.getState,
useNodeDBStore.setState,
data,
),
);
}
} }
console.debug( draft.nodeDBs = rebuilt;
"NodeDBStore: Rehydrating state with ", }),
state.nodeDBs.size, );
" nodeDBs -", },
state.nodeDBs, };
);
// Add persist middleware on the store if the feature flag is enabled
useNodeDBStore.setState( const persistNodes = featureFlags.get("persistNodeDB");
produce<PrivateNodeDBState>((draft) => { console.debug(
const rebuilt = new Map<number, NodeDB>(); `NodeDBStore: Persisting nodes is ${persistNodes ? "enabled" : "disabled"}`,
for (const [id, data] of (
draft.nodeDBs as unknown as Map<number, NodeDBData>
).entries()) {
if (data.myNodeNum !== undefined) {
// Only rebuild if there is a nodenum set otherwise orphan dbs will acumulate
rebuilt.set(
id,
nodeDBFactory(
id,
useNodeDBStore.getState,
useNodeDBStore.setState,
data,
),
);
}
}
draft.nodeDBs = rebuilt;
}),
);
},
},
),
); );
export const useNodeDBStore = persistNodes
? createStore<PrivateNodeDBState, [["zustand/persist", NodeDBPersisted]]>(
persist(nodeDBInitializer, persistOptions),
)
: createStore<PrivateNodeDBState>()(nodeDBInitializer);

3
packages/web/src/index.tsx

@ -1,5 +1,8 @@
import React from "react"; import React from "react";
import "@app/index.css"; import "@app/index.css";
// Import feature flags and dev overrides
import "@core/services/dev-overrides.ts";
import { enableMapSet } from "immer"; import { enableMapSet } from "immer";
import "maplibre-gl/dist/maplibre-gl.css"; import "maplibre-gl/dist/maplibre-gl.css";
import { Suspense } from "react"; import { Suspense } from "react";

Loading…
Cancel
Save