返回 DeepSeek-Reasonix
desktop_persistence_state.go
根目录 / desktop / desktop_persistence_state.go
1 package main
2
3 import (
4 "log/slog"
5 "sync"
6 "sync/atomic"
7
8 "reasonix/desktop/internal/draftstate"
9 "reasonix/desktop/internal/legacycleanup"
10 "reasonix/desktop/internal/sessionui"
11 "reasonix/internal/config"
12 )
13
14 // desktopPersistenceState groups process-lifetime stores and their recovery
15 // coordinator so App does not expose each lifecycle field independently.
16 type desktopPersistenceState struct {
17 desktopSessions desktopSessionState
18 desktopDrafts *draftstate.Store
19 sessionUI *sessionui.Store
20 sessionPresets *sessionPresetStore
21 manualCreationMu sync.Mutex
22 manualCreationTasks sync.WaitGroup
23 manualCreations *manualCreationManager
24 legacyCleanup *legacycleanup.Store
25 desktopMigrationDone chan struct{}
26 desktopMigrationFailed atomic.Bool
27 beforeSavedTabMigrationWait func()
28 legacyCleanupWorker legacyCleanupWorkerState
29 historicalImports historicalImportCoordinator
30 }
31
32 func newDesktopPersistenceState() desktopPersistenceState {
33 return desktopPersistenceState{
34 desktopSessions: newDesktopSessionState(),
35 desktopDrafts: draftstate.New(config.DesktopDraftStatePath()),
36 sessionUI: sessionui.New(config.DesktopSessionUIStatePath()),
37 sessionPresets: newSessionPresetStore(),
38 legacyCleanup: legacycleanup.New(config.DesktopLegacyEmptySessionCleanupPath()),
39 desktopMigrationDone: make(chan struct{}),
40 }
41 }
42
43 func (a *App) startDesktopPersistenceReconciliation() {
44 a.goSafe("reconcileCompletedLegacyCleanup", func() {
45 state, err := a.legacyCleanup.Load(a.bootContext())
46 if err != nil {
47 slog.Warn("desktop: legacy cleanup recovery unavailable", "err", err)
48 return
49 }
50 for _, item := range state.Items {
51 if item.Restored {
52 continue
53 }
54 // Only acknowledge actions already committed by the old binary.
55 // Pending candidates must never initiate a new archive.
56 if item.SessionID != "" {
57 a.reconcileLegacyCleanupArchivedOperation(item, item.SessionID)
58 }
59 if item.Phase == "archive_pending" {
60 a.reconcileLegacyCleanupTopicArchive(item)
61 }
62 }
63 })
64 a.goSafe("reconcileManualSessionCreations", a.reconcileManualSessionCreations)
65 // Workspace drafts are retired, including unsent content and interrupted
66 // draft submissions. Do not open or reconcile their historical database.
67 }
68
68 lines GO