v0.33.0 62a09f5

get_last_restorable_session.go RawHistoryFolder

1package usecase
2
3import (
4	"context"
5
6	"github.com/bnema/dumber/internal/domain/entity"
7	"github.com/bnema/dumber/internal/domain/repository"
8	"github.com/bnema/dumber/internal/logging"
9)
10
11const (
12	// maxSessionsToCheck is the number of recent sessions to check for restoration.
13	maxSessionsToCheck = 10
14)
15
16// GetLastRestorableSessionUseCase finds the most recent session that can be auto-restored.
17// A session is restorable if:
18//   - It is not the current session
19//   - It is not actively running (has ended or crashed without lock file)
20//   - It has a valid snapshot with at least one tab
21type GetLastRestorableSessionUseCase struct {
22	sessionRepo repository.SessionRepository
23	stateRepo   repository.SessionStateRepository
24}
25
26// NewGetLastRestorableSessionUseCase creates a new GetLastRestorableSessionUseCase.
27func NewGetLastRestorableSessionUseCase(
28	sessionRepo repository.SessionRepository,
29	stateRepo repository.SessionStateRepository,
30) *GetLastRestorableSessionUseCase {
31	return &GetLastRestorableSessionUseCase{
32		sessionRepo: sessionRepo,
33		stateRepo:   stateRepo,
34	}
35}
36
37// GetLastRestorableSessionInput contains the parameters for finding a restorable session.
38type GetLastRestorableSessionInput struct {
39	// ExcludeSessionID is the current session ID to exclude from results.
40	ExcludeSessionID entity.SessionID
41}
42
43// GetLastRestorableSessionOutput contains the found restorable session, if any.
44type GetLastRestorableSessionOutput struct {
45	// SessionID is the ID of the restorable session, or empty if none found.
46	SessionID entity.SessionID
47	// State is the session state to restore, or nil if none found.
48	State *entity.SessionState
49}
50
51// Execute finds the most recent restorable session.
52// Returns an empty output (not an error) if no restorable session is found.
53func (uc *GetLastRestorableSessionUseCase) Execute(
54	ctx context.Context,
55	input GetLastRestorableSessionInput,
56) (*GetLastRestorableSessionOutput, error) {
57	log := logging.FromContext(ctx)
58
59	sessions, err := uc.sessionRepo.GetRecent(ctx, maxSessionsToCheck)
60	if err != nil {
61		return nil, err
62	}
63
64	for _, session := range sessions {
65		// Only consider browser sessions
66		if session.Type != entity.SessionTypeBrowser {
67			continue
68		}
69
70		// Skip current session
71		if session.ID == input.ExcludeSessionID {
72			continue
73		}
74
75		// Skip sessions that haven't been ended yet (still running or crashed).
76		if session.IsActive() {
77			log.Debug().
78				Str("session_id", string(session.ID)).
79				Msg("auto-restore: skipping active session")
80			continue
81		}
82
83		// Try to get snapshot
84		state, err := uc.stateRepo.GetSnapshot(ctx, session.ID)
85		if err != nil {
86			log.Debug().
87				Err(err).
88				Str("session_id", string(session.ID)).
89				Msg("auto-restore: failed to get snapshot")
90			continue
91		}
92		if state == nil {
93			continue
94		}
95
96		// Skip sessions with no tabs
97		if len(state.Tabs) == 0 {
98			log.Debug().
99				Str("session_id", string(session.ID)).
100				Msg("auto-restore: skipping session with no tabs")
101			continue
102		}
103
104		// Found a valid restorable session
105		log.Info().
106			Str("session_id", string(session.ID)).
107			Int("tabs", len(state.Tabs)).
108			Int("panes", state.CountPanes()).
109			Msg("auto-restore: found restorable session")
110
111		return &GetLastRestorableSessionOutput{
112			SessionID: session.ID,
113			State:     state,
114		}, nil
115	}
116
117	// No restorable session found
118	log.Debug().Msg("auto-restore: no restorable session found")
119	return &GetLastRestorableSessionOutput{}, nil
120}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close