remote_state.go RawHistoryFolder

1package domain
2
3import (
4	"fmt"
5)
6
7// RemoteAvailability is the monitor's last-known reachability for one
8// registered endpoint. Checking is tracked separately and never replaces
9// availability: an in-flight observation preserves the previous value.
10type RemoteAvailability uint8
11
12const (
13	RemoteAvailabilityUnknown RemoteAvailability = iota + 1
14	RemoteAvailabilityReachable
15	RemoteAvailabilityUnreachable
16	RemoteAvailabilityIncompatible
17	RemoteAvailabilityAuthFailed
18	RemoteAvailabilityInvalidResponse
19	RemoteAvailabilityNoDaemon
20)
21
22// String returns the stable lowercase wire/display token for an availability.
23func (a RemoteAvailability) String() string {
24	switch a {
25	case RemoteAvailabilityUnknown:
26		return "unknown"
27	case RemoteAvailabilityReachable:
28		return "reachable"
29	case RemoteAvailabilityUnreachable:
30		return "unreachable"
31	case RemoteAvailabilityIncompatible:
32		return "incompatible"
33	case RemoteAvailabilityAuthFailed:
34		return "authentication_failed"
35	case RemoteAvailabilityInvalidResponse:
36		return "invalid_response"
37	case RemoteAvailabilityNoDaemon:
38		return "no_daemon"
39	default:
40		return "unknown"
41	}
42}
43
44// RemoteFailureKind classifies why one remote observation failed. It mirrors
45// the observation error classes without carrying raw stderr or endpoints.
46type RemoteFailureKind uint8
47
48const (
49	RemoteFailureNone RemoteFailureKind = iota
50	RemoteFailureTransport
51	RemoteFailureTimeout
52	RemoteFailureTrust
53	RemoteFailureAuthentication
54	RemoteFailureIncompatible
55	RemoteFailureInvalidResponse
56)
57
58// String returns the stable lowercase token for a failure kind.
59func (k RemoteFailureKind) String() string {
60	switch k {
61	case RemoteFailureNone:
62		return "none"
63	case RemoteFailureTransport:
64		return "transport"
65	case RemoteFailureTimeout:
66		return "timeout"
67	case RemoteFailureTrust:
68		return "trust"
69	case RemoteFailureAuthentication:
70		return "authentication"
71	case RemoteFailureIncompatible:
72		return "incompatible"
73	case RemoteFailureInvalidResponse:
74		return "invalid_response"
75	default:
76		return "transport"
77	}
78}
79
80// RemoteFailure is the typed last-failure value carried in snapshots. Err
81// preserves the underlying cause for errors.Is/As callers; Kind is the
82// sanitized classification safe for presentation and notice policy.
83type RemoteFailure struct {
84	Kind RemoteFailureKind
85	Err  error
86}
87
88// Error reports the sanitized failure kind.
89func (f RemoteFailure) Error() string { return "remote observation failed: " + f.Kind.String() }
90
91// Unwrap exposes the underlying cause to errors.Is/As.
92func (f RemoteFailure) Unwrap() error { return f.Err }
93
94// RemoteGeneration is a per-registration fencing generation. It increments
95// each time an endpoint is (re-)registered so late results bound to an older
96// generation can never apply to a newer registration of the same endpoint.
97type RemoteGeneration uint64
98
99// RemoteRegistration is the exact configured identity of one monitored
100// endpoint: the endpoint string plus a persistent random incarnation. Full
101// removal followed by re-add creates a new incarnation, so equality on both
102// fields fences ABA re-registration even when the endpoint string matches.
103type RemoteRegistration struct {
104	Endpoint    string
105	Incarnation [16]byte
106	Generation  RemoteGeneration
107}
108
109// NewRemoteRegistration creates a registration for a validated endpoint
110// with an explicit incarnation. Randomness is the caller's concern:
111// adapters sample fresh incarnations while domain stays deterministic.
112func NewRemoteRegistration(endpoint string, incarnation [16]byte) (RemoteRegistration, error) {
113	if err := ValidateRemoteHostTarget(endpoint); err != nil {
114		return RemoteRegistration{}, err
115	}
116	return RemoteRegistration{Endpoint: endpoint, Incarnation: incarnation, Generation: 1}, nil
117}
118
119// IsZero reports whether the registration carries no identity. A zero
120// incarnation never identifies a host; unbound legacy records stay zero.
121func (r RemoteRegistration) IsZero() bool {
122	return r.Endpoint == "" || r.Incarnation == [16]byte{}
123}
124
125// Equal compares exact configured identity: endpoint, incarnation and
126// generation must all match.
127func (r RemoteRegistration) Equal(other RemoteRegistration) bool {
128	return r.Endpoint == other.Endpoint && r.Incarnation == other.Incarnation && r.Generation == other.Generation
129}
130
131// Validate rejects empty endpoints and zero incarnations.
132func (r RemoteRegistration) Validate() error {
133	if err := ValidateRemoteHostTarget(r.Endpoint); err != nil {
134		return err
135	}
136	if r.Incarnation == [16]byte{} {
137		return fmt.Errorf("remote registration for %q has no incarnation", r.Endpoint)
138	}
139	if r.Generation == 0 {
140		return fmt.Errorf("remote registration for %q has no generation", r.Endpoint)
141	}
142	return nil
143}
144
145// Stable RemoteReason tokens shared by catalogue validation, picker
146// presentation, and daemon projections. Centralizing them here keeps
147// display/diagnostic labels consistent without magic strings.
148const (
149	RemoteReasonRefreshing      = "refreshing"
150	RemoteReasonCatalogStale    = "catalog_stale"
151	RemoteReasonHostUnreachable = "host_unreachable"
152	RemoteReasonVersionMismatch = "version_mismatch"
153	RemoteReasonSessionDown     = "session_down"
154	RemoteReasonSessionBroken   = "session_broken"
155	RemoteReasonSessionStopped  = "session_stopped"
156	RemoteReasonIdentityChanged = "identity_changed"
157	RemoteReasonNotFound        = "not_found"
158	RemoteReasonTimeout         = "timeout"
159	RemoteReasonMalformed       = "malformed"
160	RemoteReasonAuthFailure     = "auth_failure"
161	RemoteReasonNoDaemon        = "no_daemon"
162)

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 12

Tags 11

↑↓ moveenter openesc close