Documentation
¶
Overview ¶
Package hold is the platform-wide hold (ADR-0206 Decision 6): <storage.dataDir>/.hold exists iff the platform is held, every side-effect runner asks the Gate before it acts, and only the release deletes the marker. A restore in progress leaves restore.inprogress, which refuses a start until the operator empties what it wrote (Decision 2).
Index ¶
- Constants
- func Begin(dataDir, command string) error
- func End(dataDir string) error
- func MarkNamespaces(dataDir string, nss []v1.NamespaceName, m Marker) error
- func Own(ref string, roots ...string) error
- func Write(dataDir string, m Marker) error
- func WriteFile(op, dir, name string, data []byte) error
- func WriteReport(dataDir string, report json.RawMessage) error
- type Created
- type Evidence
- type Gate
- type Hold
- func (h *Hold) Held() bool
- func (h *Hold) HeldIn(ns v1.NamespaceName) bool
- func (h *Hold) HoldNamespace(ns v1.NamespaceName, m Marker) error
- func (h *Hold) Marker() (Marker, bool)
- func (h *Hold) NamespaceMarkers() map[v1.NamespaceName]map[string]Marker
- func (h *Hold) Release(now time.Time) error
- func (h *Hold) ReleaseNamespace(ns v1.NamespaceName, reason string) error
- func (h *Hold) ReleaseNamespaceMarker(ns v1.NamespaceName, m Marker) error
- func (h *Hold) ReleasedAt() time.Time
- func (h *Hold) ReleasedAtIn(ns v1.NamespaceName) time.Time
- func (h *Hold) Report() (json.RawMessage, error)
- type Marker
- type NamespaceGate
- type NamespaceHold
Constants ¶
const MarkerFile, BusyFile, ReleasedFile = ".hold", "restore.inprogress", ".hold-released"
The files the hold keeps in the data directory; BusyFile marks a restore in progress (Decision 2).
const NamespaceDir, NamespaceReleasedDir = ".hold-ns", ".hold-ns-released"
The per-namespace hold (ADR-0222 Decision 8): <dataDir>/.hold-ns/<ns>.<reason> holds a Marker, and a release writes its time to <dataDir>/.hold-ns-released/<ns> before it deletes the marker.
const ReasonRestore, ReasonData = "restore", "data"
The reasons a namespace is held for: an in-place Restore loading it, or a platform restore that returned its BackupSchedules without their data. HeldIn reads only these.
const ReportFile = "restore.json"
ReportFile is restore.json, the report restore run writes beside the marker (Decision 2 step 5).
Variables ¶
This section is empty.
Functions ¶
func Begin ¶
Begin writes BusyFile naming command (run, kv, blob); a BusyFile naming another command is fault.Conflict. One naming the same command is a rerun after a kill, whose directories the command itself found empty.
func MarkNamespaces ¶
func MarkNamespaces(dataDir string, nss []v1.NamespaceName, m Marker) error
MarkNamespaces writes m's marker for each of nss, offline: restore run holds the namespaces whose BackupSchedules return without their data.
func Own ¶
Own gives each root that exists, and everything below it, ref's owner and group where they differ (os.Lchown), so a restore run as root leaves what funcd, running as the data directory's owner, can open (ADR-0026 §4).
func WriteFile ¶
WriteFile replaces dir/name with data, mode 0600: a temporary file synced and renamed, then the directory synced, so a crash leaves the old file or the new one. op names the caller in the error; ADR-0207's safemode.json uses it.
func WriteReport ¶
func WriteReport(dataDir string, report json.RawMessage) error
WriteReport writes ReportFile, mode 0600, synced as Write is.
Types ¶
type Created ¶ added in v0.12.0
type Created []string
Created is the topmost directories a restore created on the way to the directories it writes: the restore gives them the data directory's owner with the rest (Own), or removes them when it fails (ADR-0206 Decision 2).
type Evidence ¶
type Evidence struct {
Held bool `json:"held"`
Marker *Marker `json:"marker,omitempty"`
ReleasedAt *v1.Timestamp `json:"releasedAt,omitempty"`
Report json.RawMessage `json:"report,omitempty"`
Counts map[v1.Kind]int `json:"counts,omitempty"`
PausedRuns []string `json:"pausedRuns,omitempty"`
DeadLetters []string `json:"deadLetters,omitempty"`
Pending map[string]map[string]int `json:"pending,omitempty"`
Orphans []string `json:"orphans,omitempty"`
BucketOrphans []string `json:"bucketOrphans,omitempty"`
FunctionsNotReady []string `json:"functionsNotReady,omitempty"`
Namespaces []NamespaceHold `json:"namespaces,omitempty"`
}
Evidence is what the hold shows the operator (Decisions 1, 8): GET …/hold returns it, `funcdctl hold status` prints it. Report is restore.json as written; runs and dead letters are <ns>/<name> and <ns>/<id>; Pending is, per <ns>/<source>, the blob keys per event a release replays; Orphans and BucketOrphans are data no object names, which the reclaims would drop; FunctionsNotReady are <ns>/<name>; Namespaces are the per-namespace markers.
type Gate ¶
Gate is what a runner asks: Held, and the time of the last release (zero when none).
var Never Gate = never{}
Never is the gate of a platform without a hold: never held, never released.
type Hold ¶
type Hold struct {
// contains filtered or unexported fields
}
Hold is the opened hold of one data directory, a Gate whose release is live.
func Open ¶
Open reads the hold of dataDir: BusyFile ⇒ fault.Conflict naming the interrupted restore; no marker ⇒ not held; a file that does not read or decode ⇒ fault.Internal.
func (*Hold) HeldIn ¶
func (h *Hold) HeldIn(ns v1.NamespaceName) bool
HeldIn reports whether the platform is held or ns holds a restore or data marker.
func (*Hold) HoldNamespace ¶
func (h *Hold) HoldNamespace(ns v1.NamespaceName, m Marker) error
HoldNamespace writes ns's marker for m.Reason and holds ns live. It never replaces a marker: ns already held for m.Reason ⇒ fault.Conflict naming the Restore of the marker that stands.
func (*Hold) NamespaceMarkers ¶
func (h *Hold) NamespaceMarkers() map[v1.NamespaceName]map[string]Marker
NamespaceMarkers is a copy of each held namespace's markers by reason.
func (*Hold) Release ¶
Release lifts the hold (Decision 8): it writes now to ReleasedFile, deletes the marker, syncs the directory, then lifts the gate. Not held ⇒ fault.Conflict.
func (*Hold) ReleaseNamespace ¶
func (h *Hold) ReleaseNamespace(ns v1.NamespaceName, reason string) error
ReleaseNamespace lifts ns's reason, as Release lifts the platform: it writes now to .hold-ns-released/<ns>, deletes the marker, syncs the directory, then lifts the gate. No such marker ⇒ fault.Conflict.
func (*Hold) ReleaseNamespaceMarker ¶
func (h *Hold) ReleaseNamespaceMarker(ns v1.NamespaceName, m Marker) error
ReleaseNamespaceMarker lifts ns's m.Reason as ReleaseNamespace does, only while that marker is still m: one another Restore wrote since ⇒ fault.Conflict.
func (*Hold) ReleasedAt ¶
ReleasedAt is the time the last release wrote to ReleasedFile, zero when none did.
func (*Hold) ReleasedAtIn ¶
func (h *Hold) ReleasedAtIn(ns v1.NamespaceName) time.Time
ReleasedAtIn is the later of ReleasedAt and ns's last release, zero when neither happened.
type Marker ¶
type Marker struct {
Reason string `json:"reason"`
Since v1.Timestamp `json:"since"`
Restore v1.ObjectName `json:"restore,omitempty"`
}
Marker is the content of MarkerFile; Reason is "restore" or "safe-mode" (ADR-0207). A namespace's restore marker also names the in-place Restore that wrote it (ADR-0222 Decision 8).
type NamespaceGate ¶
type NamespaceGate interface {
HeldIn(ns v1.NamespaceName) bool
ReleasedAtIn(ns v1.NamespaceName) time.Time
}
NamespaceGate is what a per-namespace runner asks: HeldIn is true while the platform or ns is held; ReleasedAtIn is the later of the platform's release and ns's.
var NeverNamespace NamespaceGate = never{}
NeverNamespace is the namespace gate of a platform without a hold.
type NamespaceHold ¶
type NamespaceHold struct {
Namespace v1.NamespaceName `json:"namespace"`
Marker
Phase v1.RunPhase `json:"phase,omitempty"`
}
NamespaceHold is one per-namespace marker (ADR-0222 Decision 8); Phase is the phase of the in-place Restore a restore marker names, empty once that Restore is deleted.