perf: sprint C — отделить history от IPC state-broadcast

#9  AppState больше не содержит `history` (вынесено в PersistedState
    — internal store-shape). `broadcastState()` и IPC.getState шлют
    через IPC только exercises/settings/challenges/gamesEnabled.

    Раньше каждый markDone/snooze/toggle вызывал broadcastState() →
    весь state, включая до 10k history-записей (~500KB JSON), летел
    через IPC к каждому BrowserWindow и парсился в renderer'е. На
    долгом горизонте использования становилось заметным лагом UI.

    Renderer и раньше историю из state не читал (Dashboard вызывает
    IPC.getHistory отдельно), так что это чистый perf-win без
    behavioural change. Store-internal mutations продолжают работать
    с полным PersistedState через `getState()`; renderer-bound IPC
    использует новый `getStateForRenderer()`.

Не сделано из спринта C: zustand setState refactor (#8) — текущая
архитектура работает корректно (zustand bathes), `?? []` fallback'и
в селекторах безопасны. Реальный gain был от #9, который и закрыт.
This commit is contained in:
AnRil
2026-05-22 01:18:25 +07:00
parent 4745f5e091
commit e7ccca98e7
4 changed files with 54 additions and 17 deletions

View File

@@ -16,6 +16,7 @@ import {
deleteExercise,
getHistory,
getState,
getStateForRenderer,
markDone,
setGameEnabled,
skip,
@@ -56,16 +57,14 @@ import {
export function registerIpc(): void {
ipcMain.handle(IPC.getState, () => {
// Накладываем актуальное значение autostart (источник истины — OS),
// но НЕ мутируем кэш. Раньше прямая мутация state.settings оставляла
// в RAM startWithWindows, отличающийся от persisted-disk-значения,
// и при следующем flush на диск шла OS-правда, а не пользовательский
// toggle. Сейчас возвращаем поверхностную копию.
const state = getState()
return {
...state,
settings: { ...state.settings, startWithWindows: isAutostartEnabled() }
// Без history (см. getStateForRenderer) и с актуальным значением
// autostart из OS — мутацию делаем по копии, не по cache.
const state = getStateForRenderer()
state.settings = {
...state.settings,
startWithWindows: isAutostartEnabled()
}
return state
})
ipcMain.handle(IPC.addExercise, (_e, input: unknown) => {