Files
worker/internal/workercluster/entries.go
Gleb Tv 2c7a0236da feat: publish standalone worker
Separate worker packaging and service lifecycle from the control plane.
2026-07-13 17:55:14 +03:00

153 строки
5.3 KiB
Go

package workercluster
import "encoding/json"
// EntryType enumerates the kinds of replicated log entries the FSM
// understands. Every log entry committed through the Raft Apply path
// carries an Entry of one of these kinds.
//
// The set is the subset from plan section 6.2 that this implementation
// actually exercises today. The remaining kinds are defined in
// distworker/entries.go placeholders (ObserverSetUpdate, IncidentObserve,
// ...) so later phases can add Apply branches without a wire-format
// churn.
type EntryType string
const (
// EntryConfigAdopt installs a new adopted critical-check list
// into the FSM. Replaces any previously adopted list.
EntryConfigAdopt EntryType = "config.adopt"
// EntryObserverSetUpdate installs a new observer set with a
// version stamp.
EntryObserverSetUpdate EntryType = "observer_set.update"
// EntryMembershipProposeAdd appends a Member to the membership
// cache. The Raft library itself handles the voter promotion; the
// FSM just keeps a denormalized mirror.
EntryMembershipProposeAdd EntryType = "membership.propose_add"
// EntryMembershipDemote flips a voter's role to observer.
EntryMembershipDemote EntryType = "membership.demote"
// EntryMembershipRemove drops a Member from the membership cache.
EntryMembershipRemove EntryType = "membership.remove"
// EntryIncidentObserve appends one observer vote for a check.
EntryIncidentObserve EntryType = "incident.observe"
// EntryIncidentTransition records a state transition produced by
// the FSM from committed observations.
EntryIncidentTransition EntryType = "incident.transition"
// EntryOutboxEnqueue appends notification outbox metadata.
EntryOutboxEnqueue EntryType = "outbox.enqueue"
// EntryOutboxDelivered marks an outbox entry as delivered.
EntryOutboxDelivered EntryType = "outbox.delivered"
// EntryOutboxAck records a delivery ack / duplicate marker.
EntryOutboxAck EntryType = "outbox.ack"
// EntryPartitionReport stores the cluster's view of network
// partition state.
EntryPartitionReport EntryType = "partition.report"
// EntryDiagnosticsUpdate stores per-worker health metadata.
EntryDiagnosticsUpdate EntryType = "diagnostics.update"
)
// Entry is the wire format the FSM expects on every Apply. The Data
// field holds the JSON-encoded payload of the matching struct.
type Entry struct {
Type EntryType `json:"type"`
Term uint64 `json:"term,omitempty"`
Index uint64 `json:"index,omitempty"`
ActorID string `json:"actor_id,omitempty"`
Version uint64 `json:"version,omitempty"`
Adopted json.RawMessage `json:"adopted,omitempty"`
Set json.RawMessage `json:"set,omitempty"`
Member json.RawMessage `json:"member,omitempty"`
State json.RawMessage `json:"state,omitempty"`
Observe json.RawMessage `json:"observe,omitempty"`
Outbox json.RawMessage `json:"outbox,omitempty"`
OutboxID uint64 `json:"outbox_seq,omitempty"`
Report json.RawMessage `json:"report,omitempty"`
Diag json.RawMessage `json:"diag,omitempty"`
}
// ConfigAdoptPayload is the body of an EntryConfigAdopt entry.
type ConfigAdoptPayload struct {
Version uint64 `json:"version"`
Actor string `json:"actor"`
Checks []CriticalCheckConfig `json:"checks"`
}
// ObserverSetPayload is the body of an EntryObserverSetUpdate entry.
type ObserverSetPayload struct {
Set ObserverSet `json:"set"`
}
// MemberPayload is the body of an EntryMembershipProposeAdd,
// EntryMembershipDemote, and EntryMembershipRemove entries.
type MemberPayload struct {
Member Member `json:"member"`
Reason string `json:"reason,omitempty"`
Prev *Member `json:"prev,omitempty"` // populated on demote/remove
}
// IncidentObservePayload is one observer vote for a check.
type IncidentObservePayload struct {
CheckID int64 `json:"check_id"`
WorkerID string `json:"worker_id"`
Label string `json:"label"` // ok | warn | down | unknown
ObservedIx uint64 `json:"observed_at_index"`
}
// IncidentTransitionPayload is the FSM-produced state transition
// recorded after a quorum rule fires.
type IncidentTransitionPayload struct {
CheckID int64 `json:"check_id"`
State IncidentState `json:"state"`
Reason string `json:"reason,omitempty"`
}
// OutboxPayload is the body of an EntryOutboxEnqueue entry.
type OutboxPayload struct {
Entry OutboxMeta `json:"entry"`
}
// OutboxUpdatePayload is the body of EntryOutboxDelivered and
// EntryOutboxAck entries.
type OutboxUpdatePayload struct {
Seq uint64 `json:"seq"`
State string `json:"state"`
Attempts int `json:"attempts"`
LastError string `json:"last_error,omitempty"`
}
// PartitionReportPayload is the body of an EntryPartitionReport entry.
type PartitionReportPayload struct {
State PartitionState `json:"state"`
}
// DiagnosticsPayload is the body of an EntryDiagnosticsUpdate entry.
type DiagnosticsPayload struct {
Diag WorkerDiagnostics `json:"diag"`
}
// EncodeEntry marshals a fully-populated Entry to JSON bytes ready to
// hand to raft.Apply.
func EncodeEntry(e *Entry) ([]byte, error) {
return json.Marshal(e)
}
// DecodeEntry parses Entry bytes back into the wire struct.
func DecodeEntry(b []byte) (Entry, error) {
var e Entry
if err := json.Unmarshal(b, &e); err != nil {
return e, err
}
return e, nil
}