feat(stovepipe): queue-scoped storage parity — factory contract, bound stores, queue-leading keys - #539
Merged
Conversation
behinddwalls
marked this pull request as ready for review
August 6, 2026 17:01
mnoah1
approved these changes
Aug 6, 2026
behinddwalls
force-pushed
the
preetam/storage-profile-routing
branch
from
August 6, 2026 20:49
29c8606 to
0cc7ace
Compare
…d stores, queue-leading keys
## Summary
### Why?
Stovepipe's storage kept the pre-factory shape after submitqueue's seam moved to per-queue resolution: a queue-blind singleton aggregate, bare-ID keys on `request` and `build`, and controllers that learn a message's queue only by loading the entity. This brings the domain to full parity with the submitqueue contract so both storage seams read, route, and isolate the same way.
### What?
The stovepipe internal queue payloads (`ProcessRequest`, `BuildRequest`, `BuildSignal`, `Record`) gain an additive `queue_name` echoed by every publisher from the entity it holds; consumers resolve their bound store set from it and guard that it matches the loaded request's queue. The storage extension gains `Config{QueueName}` and a `Factory`; the aggregate is queue-bound with no global remainder — stovepipe has no cross-queue read paths, and `QueueStore`, whose row key is the queue name itself, binds naturally (reads outside the binding miss, writes are rejected). `RequestURIStore` drops its explicit queue parameters in favor of the binding. The `request` table moves to a `(queue, id)` primary key and `build` gains a queue column with a `(queue, id)` key, so runner-minted build IDs no longer need cross-queue uniqueness; `request_uri` and `queue` were already queue-keyed. The MySQL backend keeps one shared pool with `For` binding a queue over it, and the host wiring adapts it into the factory seam. The contract suite becomes factory-driven with cross-queue isolation cases for the URI mapping and queue rows.
## Test Plan
✅ `go test ./...` ✅ stovepipe storage contract suite, service integration suite, and stovepipe e2e via bazel (local runs need `--sandbox_writable_path=$HOME/.docker`) ✅ `make fmt` ✅ `make lint` ✅ `make check-tidy` ✅ `make check-gazelle`. Schemas are pre-production: tables recreated, no data migration.
behinddwalls
force-pushed
the
preetam/stovepipe-storage-parity
branch
from
August 6, 2026 20:49
616eb6b to
eccdf53
Compare
behinddwalls
changed the base branch from
preetam/storage-profile-routing
to
main
August 6, 2026 20:49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Why?
Stovepipe's storage kept the pre-factory shape after submitqueue's seam moved to per-queue resolution: a queue-blind singleton aggregate, bare-ID keys on
requestandbuild, and controllers that learn a message's queue only by loading the entity. This brings the domain to full parity with the submitqueue contract so both storage seams read, route, and isolate the same way.What?
The stovepipe internal queue payloads (
ProcessRequest,BuildRequest,BuildSignal,Record) gain an additivequeue_nameechoed by every publisher from the entity it holds; consumers resolve their bound store set from it and guard that it matches the loaded request's queue. The storage extension gainsConfig{QueueName}and aFactory; the aggregate is queue-bound with no global remainder — stovepipe has no cross-queue read paths, andQueueStore, whose row key is the queue name itself, binds naturally (reads outside the binding miss, writes are rejected).RequestURIStoredrops its explicit queue parameters in favor of the binding. Therequesttable moves to a(queue, id)primary key andbuildgains a queue column with a(queue, id)key, so runner-minted build IDs no longer need cross-queue uniqueness;request_uriandqueuewere already queue-keyed. The MySQL backend keeps one shared pool withForbinding a queue over it, and the host wiring adapts it into the factory seam. The contract suite becomes factory-driven with cross-queue isolation cases for the URI mapping and queue rows.Test Plan
✅
go test ./...✅ stovepipe storage contract suite, service integration suite, and stovepipe e2e via bazel (local runs need--sandbox_writable_path=$HOME/.docker) ✅make fmt✅make lint✅make check-tidy✅make check-gazelle. Schemas are pre-production: tables recreated, no data migration.