Documentation
¶
Overview ¶
Package cluster is what lets several Pando processes serve one install against one database (issue #72).
Each process is a replica. A replica registers itself, heartbeats, and is taken to have stopped when it goes quiet; work it had under way is then recorded as interrupted by whichever replica leads. One replica at a time leads, and only the leader runs the jobs that must happen once per install — garbage collection, auto-deploy, audit retention — rather than once per process.
This is not scheduling (R-010). A replica is Pando's own process, never a place an app runs, and nothing here decides where a workload goes. The apps run where the runtime adapter puts them, exactly as with one replica.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Leader ¶
type Leader struct {
Store Leadership
Jobs []Job
Logger *zap.Logger
// Retry is how often a follower tries to lead, and how often a leader
// checks it still is. Ten seconds when zero.
Retry time.Duration
// contains filtered or unexported fields
}
Leader runs Jobs on whichever one replica holds the leader lock.
A lock for the whole set rather than one per job: the jobs are a handful of slow loops, and one leader is one place to look when asking "who is running the GC". A replica that loses the lock cancels every job and waits for them to stop before it tries to lead again, so two never run a job at once.
type Leadership ¶
type Leadership interface {
TryLead(ctx context.Context, check time.Duration) (*state.Leadership, bool, error)
}
Leadership is the slice of state.Replicas a leader uses.
type LogOwner ¶
type LogOwner struct {
Self string
Deployments interface {
Runner(ctx context.Context, deploymentID string) (string, error)
Waiting(ctx context.Context, deploymentID string) (bool, error)
}
Replicas interface {
ByID(ctx context.Context, replicaID string) (state.Replica, bool, error)
}
// ClaimWait is how long to wait for a queued deploy to be claimed before
// answering (O-32): until then nobody holds its log, and answering "this
// replica" would follow a log another replica is about to write. A
// minute when zero.
ClaimWait time.Duration
}
LogOwner finds the base URL of the live replica running a deployment, or "" when it is this replica, or no live replica is: the answer to "where is this deploy's live log" (issue #72).
type Member ¶
type Member struct {
Store Store
ID string
Hostname string
AdvertiseURL string
Version string
Minter *assertion.Minter
Logger *zap.Logger
// Interval is how often to heartbeat; state.HeartbeatInterval if zero.
Interval time.Duration
}
Member is this process's membership of the install.
func (*Member) Join ¶
Join registers this replica and publishes its signing key. Before the server listens: an assertion this replica signs must be verifiable from the first request it serves.
func (*Member) Run ¶
Run heartbeats until ctx ends, and returns early — with the reason — when this replica should restart: a restart was asked for (POST /restart reaches every replica, not only the one that received it), or the install has taken this replica for dead and abandoned its work, after which carrying on under the same identity would be a lie.
type Store ¶
type Store interface {
Register(ctx context.Context, rep state.Replica) error
Heartbeat(ctx context.Context, replicaID string) (bool, error)
Stop(ctx context.Context, replicaID string) error
RestartPending(ctx context.Context, replicaID string) (bool, error)
VerificationKeys(ctx context.Context, validity time.Duration) ([]state.Replica, error)
}
Store is the slice of state.Replicas a member uses.