Give each pending assignment its own condition, and keep a raised row until it clears
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery-group group fix/assign-says-why-a-module-is-not-there delivering: 1 of 2 delivered
mesh/delivery superseded: a newer delivery to the same trunk took over its walk
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery-group group fix/assign-says-why-a-module-is-not-there delivering: 1 of 2 delivered
mesh/delivery superseded: a newer delivery to the same trunk took over its walk
Second review of #150: one key per machine and module let a newer failure be cleared in the tick that raised it, pruning could orphan an open condition, and a build no longer waited for read as never asked although it may still run.
This commit is contained in:
@@ -76,6 +76,11 @@ func (b *natsBuilds) Ask(ctx context.Context, request BuildRequest) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ErrNotHandedOver is a Submit that failed before the build was handed to the build seat: nothing runs. Any
|
||||
// other error from Submit came after: the build may still run, and its outcome may still come (novox/hq
|
||||
// issue 325).
|
||||
var ErrNotHandedOver = errors.New("the build was not handed over")
|
||||
|
||||
func (b *natsBuilds) Submit(ctx context.Context, request BuildRequest,
|
||||
wait time.Duration) (BuildResult, error) {
|
||||
|
||||
@@ -84,23 +89,23 @@ func (b *natsBuilds) Submit(ctx context.Context, request BuildRequest,
|
||||
// the same event on EVENTS, which the controller records.
|
||||
outcomes, err := b.js.Conn().SubscribeSync(BuildOutcomeOf(b.role()))
|
||||
if err != nil {
|
||||
return BuildResult{}, fmt.Errorf("cannot listen for a build's outcome: %w", err)
|
||||
return BuildResult{}, fmt.Errorf("%w: cannot listen for a build's outcome: %w", ErrNotHandedOver, err)
|
||||
}
|
||||
defer func() { _ = outcomes.Unsubscribe() }()
|
||||
if err := b.js.Conn().Flush(); err != nil {
|
||||
return BuildResult{}, err
|
||||
return BuildResult{}, fmt.Errorf("%w: %w", ErrNotHandedOver, err)
|
||||
}
|
||||
|
||||
body, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
return BuildResult{}, err
|
||||
return BuildResult{}, fmt.Errorf("%w: %w", ErrNotHandedOver, err)
|
||||
}
|
||||
// Into the role's work queue and awaited: work the bus never accepted must fail here rather than
|
||||
// be assumed, because nothing else will ever say so.
|
||||
publish, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||
defer cancel()
|
||||
if _, err := b.js.Context().Publish(BuildWorkOf(b.role()), body, nats.Context(publish)); err != nil {
|
||||
return BuildResult{}, fmt.Errorf("cannot submit a build: %w", err)
|
||||
return BuildResult{}, fmt.Errorf("%w: cannot submit a build: %w", ErrNotHandedOver, err)
|
||||
}
|
||||
|
||||
waiting, cancelWait := context.WithTimeout(ctx, wait)
|
||||
|
||||
Reference in New Issue
Block a user