Skip to content

feat(stovepipe): add and wire the buildsignal stage controller#409

Open
roychying wants to merge 2 commits into
chenghan.ying/stovepipe-wire-build-stepfrom
chenghan.ying/stovepipe-buildsignal-controller
Open

feat(stovepipe): add and wire the buildsignal stage controller#409
roychying wants to merge 2 commits into
chenghan.ying/stovepipe-wire-build-stepfrom
chenghan.ying/stovepipe-buildsignal-controller

Conversation

@roychying

Copy link
Copy Markdown
Contributor

What?

Adds stovepipe/controller/buildsignal plus the new Record queue message/proto and TopicKeyRecord. Process consumes a BuildSignal (build id), loads Build+Request, no-ops if the request is terminal, polls buildRunner.Status, persists a real status transition via CAS (BuildStore.Update) with terminal status write-once (a later poll of a flaky backend can never overwrite an already-committed terminal status), and either reschedules itself via PublishAfter (5s while accepted, 2s while running) or, once terminal, publishes to record. Wires the controller into main.go and registers the buildsignal (subscribed) and record (publish-only, no consumer yet) topics.

Test Plan

make build, make test - all clean.

Issue

@roychying
roychying requested review from a team, behinddwalls and sbalabanov as code owners July 20, 2026 23:24
@roychying roychying changed the title Chenghan.ying/stovepipe buildsignal controller feat(stovepipe): wire the build controller into the server Jul 20, 2026
@roychying roychying closed this Jul 20, 2026
@roychying roychying reopened this Jul 20, 2026
@roychying roychying changed the title feat(stovepipe): wire the build controller into the server feat(stovepipe): add and wire the buildsignal stage controller Jul 20, 2026
@roychying
roychying force-pushed the chenghan.ying/stovepipe-buildsignal-controller branch from 7459fe1 to 63562b5 Compare July 21, 2026 00:01
Comment on lines +45 to +51
// PollDelayAcceptedMs is the delay before the next Status call while the
// build is queued by the runner but has not started executing.
PollDelayAcceptedMs int64 = 5000
// PollDelayRunningMs is the delay before the next Status call while the
// build is executing.
PollDelayRunningMs int64 = 2000
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this needs to be configurable and come via controller inputs eventially, can you add TODO to do so

buildRunner, err := c.buildRunners.For(buildrunner.Config{QueueName: request.Queue})
if err != nil {
// A queue with no registered builder is a config error.
return fmt.Errorf("BuildSignalController failed to resolve build runner for queue %s: %w", request.Queue, err)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BuildSignalController marker? can we remove those?

// loadRequest returns the request for id. A miss here is almost certainly a
// lagging read behind the Build that referenced it, so it is retryable; a
// genuinely orphaned Build still dead-letters at MaxAttempts.
func (c *Controller) loadRequest(ctx context.Context, id string) (entity.Request, error) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i see it being duplicated between build and buildsignal

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should align on this more generally. Do we want to make each controller own its own logic for fetching required entities, or have some kind of intermediate later - e.g. how we typically put all database / retrieval operations behind a repository package in our internal services and it just returns the entity.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like in submitqueue most controllers have been handling it themselves so far but it could lead to duplication.

if err == nil {
return got, nil
}
if errors.Is(err, storage.ErrNotFound) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as other PR, why do we need to handle not found?

@mnoah1 mnoah1 Jul 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've noticed agents tend to add this as a defense against DB replication lag, maybe won't happen much in the real world but feels reasonable to guard against.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants