Each act that changed what a node runs now writes that node's compositions, and its wants follow by the assigner's rules; a bus upgrade composes the bus's machines and answers the want the operator writes, since the assigner never moves the bus (ADR 0539 clauses 5, 7 and 15). A node-engine may ask its own backup holder before a data module moves.
72 lines
3.7 KiB
Go
72 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
// A new controller's own grants reach the bus before it writes (novox/hq issue 1800).
|
|
//
|
|
// A controller's grants are composed by the controller binary itself (broker.PermissionsFor), so the controller that
|
|
// walks a delivery cannot put its successor's grants in the bus's user list: the list that carries them was sent only
|
|
// once the new controller passed its gate on its first machine (carryUserList). Until then the new controller wrote
|
|
// buckets its account was not granted, and the bus refused them: plans-building on 2026-10-21, declared-packages on
|
|
// 2026-10-22, and R4e's states-announced would be the third.
|
|
//
|
|
// So a controller that starts, holding the lease and before it starts anything that writes its buckets, sends the
|
|
// machine holding the bus its user list when the list it composes is not the one that machine was last sent: the grants
|
|
// step's send (release.go grantsStep), every build there kept at the one it runs, refused unsent when the declaration
|
|
// would change more than the user list (errNotGrantsOnly). No build of a running plan reaches that machine before the
|
|
// plan's own tier sends it (ADR 0503 §8). A send that cannot be made is said once, and the controller serves on.
|
|
//
|
|
// It does not ask heldMachines, as carryUserList does: every reason that gives is a build that would move with the
|
|
// list (a policy, a plan not yet sent there, no gate passed), and here none can. The running plan that brought this
|
|
// controller holds the bus's machine until its tier sends it; asking would leave the list behind exactly when 1800
|
|
// meets it. The refusal unsent (errNotGrantsOnly) is the guard instead.
|
|
|
|
// ownGrantsCarrier is what the start's send reads and does: whether the bus's list is behind and on which machine, and
|
|
// the grants-only send to it. Variables so a test needs no store and no bus.
|
|
type ownGrantsCarrier struct {
|
|
behind func(ctx context.Context) (holder string, behind bool, err error)
|
|
send func(ctx context.Context, holder string) error
|
|
}
|
|
|
|
// carry sends the machine holding the bus the controller's own user list when it is behind, and says what it did.
|
|
func (c ownGrantsCarrier) carry(ctx context.Context) string {
|
|
holder, behind, err := c.behind(ctx)
|
|
switch {
|
|
case err != nil:
|
|
return fmt.Sprintf("whether the bus's user list carries this controller's grants cannot be read, so it is not sent "+
|
|
"at start; a bucket it newly writes may be refused until the gate carries it: %v", err)
|
|
case holder == "" || !behind:
|
|
return ""
|
|
}
|
|
if err := c.send(ctx, holder); err != nil {
|
|
return fmt.Sprintf("this controller's grants could not be sent to %s, which holds the bus, at its start; a bucket "+
|
|
"it newly writes may be refused until the gate carries them: %v", holder, err)
|
|
}
|
|
return fmt.Sprintf("sent %s, which holds the bus, this controller's user list alone, every build there kept, "+
|
|
"before it writes", holder)
|
|
}
|
|
|
|
// startWithOwnGrants carries the controller's own grants to the bus and only then starts what writes (then).
|
|
func startWithOwnGrants(ctx context.Context, c ownGrantsCarrier, then func()) {
|
|
if said := c.carry(ctx); said != "" {
|
|
fmt.Println(said)
|
|
}
|
|
then()
|
|
}
|
|
|
|
// ownGrantsOf is the carrier of the serving controller: the grants step's reading and its grants-only send.
|
|
func ownGrantsOf(open *stores) ownGrantsCarrier {
|
|
return ownGrantsCarrier{
|
|
behind: func(ctx context.Context) (string, bool, error) { return brokerBehind(ctx, open, nil) },
|
|
send: func(ctx context.Context, holder string) error {
|
|
// The user list is a file of the bus module's composition (novox/hq ADR 0539 clause 7): composed, and the
|
|
// assigner writes the bus node's want for that revision at once.
|
|
_, err := composeModules(ctx, open, []string{holder})
|
|
return err
|
|
},
|
|
}
|
|
}
|