返回 DeepSeek-Reasonix
historical_legacy_reconciliation_worker.go
根目录 / desktop / historical_legacy_reconciliation_worker.go
1 package main
2
3 import (
4 "context"
5 "errors"
6 "log/slog"
7 )
8
9 type historicalLegacyReconcileState struct {
10 pending bool
11 dirty bool
12 }
13
14 // The metadata catalog can finish after the startup historical pass. Coalesce
15 // its completion events so missing legacy receipts recover on the same launch,
16 // without a second directory scan or work on the renderer's read path.
17 func (a *App) requestHistoricalLegacyReconciliation(ctx context.Context) {
18 c := &a.historicalImports
19 c.mu.Lock()
20 if !c.catalogEnabled || c.stopped || ctx.Err() != nil || a.shuttingDown.Load() {
21 c.mu.Unlock()
22 return
23 }
24 c.legacyReconcile.dirty = true
25 if c.legacyReconcile.pending {
26 c.mu.Unlock()
27 return
28 }
29 c.legacyReconcile.pending = true
30 c.workers.Add(1)
31 workerCtx := c.ctx
32 c.mu.Unlock()
33 go func() {
34 defer c.workers.Done()
35 for {
36 c.mu.Lock()
37 if c.stopped || workerCtx.Err() != nil || !c.legacyReconcile.dirty {
38 c.legacyReconcile.pending = false
39 c.mu.Unlock()
40 return
41 }
42 c.legacyReconcile.dirty = false
43 c.mu.Unlock()
44 if err := a.reconcileDiscoveredLegacyCatalog(workerCtx); err != nil && !errors.Is(err, context.Canceled) {
45 slog.Warn("desktop: legacy receipt recovery deferred")
46 }
47 }
48 }()
49 }
50
51 func (a *App) reconcileDiscoveredLegacyCatalog(ctx context.Context) error {
52 c := &a.historicalImports
53 c.discoveryMu.Lock()
54 defer c.discoveryMu.Unlock()
55 before, err := a.workspaceRegistry().Load(ctx)
56 if err != nil {
57 return err
58 }
59 sources := map[string]historicalSource{}
60 if err := a.addHistoricalCatalogReceipts(ctx, func(path, format, scope, root, head string) {
61 sources[desktopSourceKey(path, head)] = historicalSource{path: path, format: format, scope: scope, root: root, head: head}
62 }); err != nil {
63 return err
64 }
65 if err := a.reconcileHistoricalLegacyCatalog(ctx, sources); err != nil {
66 return err
67 }
68 after, err := a.workspaceRegistry().Load(ctx)
69 if err == nil && before.Generation != after.Generation {
70 a.emitProjectTreeChangedEvent()
71 }
72 return err
73 }
74
74 lines GO