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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user