feat(M6): token-ring incremental log sync — append-only op log, delta rides token round-2, nodes converge on identical history (e2e verified join events)

This commit is contained in:
2026-08-18 08:59:59 +08:00
parent f6c4b91a96
commit e59feb82c1
10 changed files with 635 additions and 34 deletions

View File

@ -44,18 +44,18 @@ func (l Load) Score() float64 { return l.MemPct + l.NetPct }
// intermediate forwarding intent (local/remote/link) — NOT a rendered frpc
// config. The claiming node renders its local frpc config and spawns the worker.
type Task struct {
ID string `json:"id"`
Local store.Local `json:"local"`
Remote store.Remote `json:"remote"`
Link store.Link `json:"link"`
Created int64 `json:"created"`
ID string `json:"id"`
Local store.Local `json:"local"`
Remote store.Remote `json:"remote"`
Link store.Link `json:"link"`
Created int64 `json:"created"`
}
// TopoEntry is an ESTABLISHED forward in the cluster topology: who (OwnerID)
// runs which forward (rendered from the same intermediate intent).
type TopoEntry struct {
TaskID string `json:"taskId"`
OwnerID string `json:"ownerId"`
TaskID string `json:"taskId"`
OwnerID string `json:"ownerId"`
Local store.Local `json:"local"`
Remote store.Remote `json:"remote"`
Link store.Link `json:"link"`
@ -65,23 +65,24 @@ type TopoEntry struct {
// State is the full cluster picture, replicated on every node:
// ring membership + pending tasks + active forward topology.
type State struct {
LeaderID string `json:"leaderId"`
Nodes []Node `json:"nodes"`
Cycle int64 `json:"cycle"`
LeaderID string `json:"leaderId"`
Nodes []Node `json:"nodes"`
Cycle int64 `json:"cycle"`
RoundDelay time.Duration `json:"-"`
// PendingTasks: not yet claimed (disappear when claimed).
PendingTasks map[string]*Task `json:"pendingTasks,omitempty"`
// Topology: active forwards owned by members (full cluster view).
Topology map[string]*TopoEntry `json:"topology,omitempty"`
Seq int64 `json:"seq"`
Seq int64 `json:"seq"`
}
// Token is the circulating message: one physical token, two phases per cycle.
type Token struct {
Cycle int64 `json:"cycle"`
Phase int `json:"phase"`
State State `json:"state"`
Passed []string `json:"passed,omitempty"`
Cycle int64 `json:"cycle"`
Phase int `json:"phase"`
State State `json:"state"`
Log []LogEntry `json:"logDelta,omitempty"`
Passed []string `json:"passed,omitempty"`
SentAt int64 `json:"sentAt,omitempty"`
}