A repeat assignment says nothing changed (ADR 0115)
One assignment of a module per node is now the rule, not a limitation — the operator dropped the multi-assignment requirement, and the schema's (node, module) key has been the decision since migration 0005. What changed: Assign reports whether the assignment was new, and the command says 'already runs — one node runs one of each (ADR 0115); nothing changed' instead of printing 'is assigned' for a no-op, which read as an action that happened. Idempotence stays: a repeat is exit 0, because a script stating what is already true is not wrong.
This commit is contained in:
@@ -430,27 +430,36 @@ func (i *Inventory) discard(ctx context.Context, name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Assign puts a module on a node.
|
||||
// Assign puts a module on a node, and says whether that is new.
|
||||
//
|
||||
// Records the intention and checks nothing. Whether the set of assignments can actually become a
|
||||
// declaration is resolution's question, asked over the whole set at once — and asking it here,
|
||||
// one module at a time, would let an assignment look accepted and then refuse when a second
|
||||
// arrives.
|
||||
func (i *Inventory) Assign(ctx context.Context, nodeName, module string) error {
|
||||
//
|
||||
// **One assignment of a module per node is the rule, not a race lost** (novox/hq ADR 0115). The
|
||||
// module's name is the assignment's identity — its database user, its broker account, its
|
||||
// containers and its placed directory are all named by it — so the schema's (node, module) key
|
||||
// is the decision, and a repeat is absorbed rather than refused. Absorbed audibly: the caller is
|
||||
// told nothing changed, because "is assigned" printed for a no-op reads as an action.
|
||||
func (i *Inventory) Assign(ctx context.Context, nodeName, module string) (bool, error) {
|
||||
node, err := i.NodeByName(ctx, nodeName)
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
if err := i.runsSomewhere(ctx, module); err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
_, err = i.store.Pool().Exec(ctx,
|
||||
tag, err := i.store.Pool().Exec(ctx,
|
||||
`insert into assignment (node, module) values ($1, $2) on conflict do nothing`,
|
||||
node.ID, module)
|
||||
if err != nil && strings.Contains(err.Error(), "assignment_module_fkey") {
|
||||
return fmt.Errorf("%w: %s", ErrNoSuchModule, module)
|
||||
return false, fmt.Errorf("%w: %s", ErrNoSuchModule, module)
|
||||
}
|
||||
return err
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return tag.RowsAffected() > 0, nil
|
||||
}
|
||||
|
||||
// Unassign takes a module off a node.
|
||||
|
||||
Reference in New Issue
Block a user