Caught up is an equality, not an ordering
The report carries the digest of the declaration it applied (mesh-host 8211d8b), and the mesh stores it beside the outcome. `reported` rows in the status JSON now say `current`: whether the machine's last word names the declaration last sent. Not derivable from the timestamps beside it, which is why they were not enough: an apply begun under the previous declaration reports after the next send — newer, and still about the old words. The lab lost exactly that race between one test's closing push and the next test's opening one. Empty digests — every host from before reports carried one — read as not current, which errs toward waiting rather than toward asserting on files that are not there yet.
This commit is contained in:
@@ -429,6 +429,9 @@ type Doing struct {
|
||||
Failed []FailedResource
|
||||
Applied int
|
||||
At time.Time
|
||||
// Declared is the digest of the declaration the report was about; empty when the machine
|
||||
// did not say.
|
||||
Declared string
|
||||
}
|
||||
|
||||
// FailedResource is one thing a node could not do.
|
||||
@@ -451,11 +454,12 @@ func (i *Inventory) RecordDoing(ctx context.Context, node string, d Doing) error
|
||||
return err
|
||||
}
|
||||
_, err = i.store.Pool().Exec(ctx,
|
||||
`insert into node_report (node, outcome, refused, failed, applied, at)
|
||||
values ($1, $2, $3, $4, $5, now())
|
||||
`insert into node_report (node, outcome, refused, failed, applied, at, declared)
|
||||
values ($1, $2, $3, $4, $5, now(), $6)
|
||||
on conflict (node) do update set outcome = excluded.outcome, refused = excluded.refused,
|
||||
failed = excluded.failed, applied = excluded.applied, at = excluded.at`,
|
||||
node, d.Outcome, d.Refused, failed, d.Applied)
|
||||
failed = excluded.failed, applied = excluded.applied, at = excluded.at,
|
||||
declared = excluded.declared`,
|
||||
node, d.Outcome, d.Refused, failed, d.Applied, d.Declared)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -528,12 +532,17 @@ type Reported struct {
|
||||
At *time.Time
|
||||
// Sent is when the current declaration went to it; nil if nothing ever did.
|
||||
Sent *time.Time
|
||||
// Current is whether the last report names the declaration last sent — the machine has
|
||||
// acted on the current words, not merely spoken after they were written. False also covers
|
||||
// a machine that has not said which, which is every host from before reports carried it.
|
||||
Current bool
|
||||
}
|
||||
|
||||
// LastReports is every machine's last report beside when it was last sent a declaration.
|
||||
func (i *Inventory) LastReports(ctx context.Context) ([]Reported, error) {
|
||||
rows, err := i.store.Pool().Query(ctx,
|
||||
`select n.name, coalesce(r.outcome, ''), r.at, n.sent_at
|
||||
`select n.name, coalesce(r.outcome, ''), r.at, n.sent_at,
|
||||
r.declared is not null and r.declared <> '' and r.declared = n.sent
|
||||
from node n left join node_report r on r.node = n.id
|
||||
order by n.name`)
|
||||
if err != nil {
|
||||
@@ -543,7 +552,7 @@ func (i *Inventory) LastReports(ctx context.Context) ([]Reported, error) {
|
||||
var out []Reported
|
||||
for rows.Next() {
|
||||
var r Reported
|
||||
if err := rows.Scan(&r.Node, &r.Outcome, &r.At, &r.Sent); err != nil {
|
||||
if err := rows.Scan(&r.Node, &r.Outcome, &r.At, &r.Sent, &r.Current); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, r)
|
||||
|
||||
Reference in New Issue
Block a user