Pass a seat held once to its only claimant when its recorded holder is assigned nowhere (issue 1317, ADR 0449)

This commit is contained in:
2026-10-19 21:21:32 +00:00
parent caa3fc8995
commit 666dcff79b
7 changed files with 467 additions and 2 deletions
+42
View File
@@ -284,6 +284,48 @@ func (i *Inventory) HoldSeat(ctx context.Context, seat, scope, nodeName, module
return tx.Commit(ctx)
}
// PassSeat records `to` as the holder of a seat held once in place of `from`, only while `from` is still the
// one on record: a compare-and-set in one transaction, so two compositions reading the same record cannot both
// hand the seat over (novox/hq ADR 0449 §4). It answers false, with no error, when the record no longer names
// `from` (another composition passed it first). The new holder must be an assignment.
func (i *Inventory) PassSeat(ctx context.Context, seat, scope string, from, to catalogue.Held) (bool, error) {
fromNode, err := i.NodeByName(ctx, from.Node)
if err != nil {
return false, err
}
toNode, err := i.NodeByName(ctx, to.Node)
if err != nil {
return false, err
}
if err := i.mustBeAssigned(ctx, seat, to.Node, to.Module); err != nil {
return false, err
}
tx, err := i.store.Pool().Begin(ctx)
if err != nil {
return false, err
}
defer func() { _ = tx.Rollback(context.WithoutCancel(ctx)) }()
gone, err := tx.Exec(ctx,
`delete from seat_holding where seat = $1 and node = $2 and module = $3`,
seat, fromNode.ID, from.Module)
if err != nil {
return false, fmt.Errorf("passing %s from %s on %s: %w", seat, from.Module, from.Node, err)
}
if gone.RowsAffected() == 0 {
return false, nil
}
if _, err := tx.Exec(ctx,
`delete from seat_holding where seat = $1`, seat); err != nil {
return false, fmt.Errorf("passing %s: %w", seat, err)
}
if _, err := tx.Exec(ctx,
`insert into seat_holding (seat, scope, node, module) values ($1, $2, $3, $4)`,
seat, scope, toNode.ID, to.Module); err != nil {
return false, fmt.Errorf("recording %s on %s as the holder of %s: %w", to.Module, to.Node, seat, err)
}
return true, tx.Commit(ctx)
}
// AddSeatHolder records one more assignment holding a replicated seat, beside those already on
// record (novox/hq ADR 0223). Whether the seat may have several holders is the caller's to judge —
// the seat's definition is compiled, and the store holds no column for it. Recording a holder