A new controller's grants reached the bus only after its gate, so the buckets it newly writes were refused until then. At start it now sends the bus's machine the user list alone, every build there kept.
70 lines
3.6 KiB
Go
70 lines
3.6 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 brokerBehindOf(ctx, open, nil) },
|
|
send: func(ctx context.Context, holder string) error {
|
|
_, err := sendRollout(keepingEveryBuild(withScope(ctx, sendScope{}), holder), open, []string{holder})
|
|
return err
|
|
},
|
|
}
|
|
}
|