Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion platform/consumer/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ type topicGroup struct {
}

// NewTopicRegistry creates a new TopicRegistry from a list of TopicConfigs.
// Returns an error if any topic name is invalid.
// Returns an error if any topic name is invalid, or if two configs share a
// topic key — a duplicate key would silently shadow the earlier entry (last
// write wins on the key→queue/name maps), routing publishes and subscriptions
// registered against one topic onto another.
func NewTopicRegistry(configs []TopicConfig) (TopicRegistry, error) {
queues := make(map[TopicKey]extqueue.Queue, len(configs))
topicNames := make(map[TopicKey]string, len(configs))
Expand All @@ -73,6 +76,12 @@ func NewTopicRegistry(configs []TopicConfig) (TopicRegistry, error) {
return TopicRegistry{}, fmt.Errorf("invalid topic name for key %s: %w", cfg.Key, err)
}

if existing, ok := topicNames[cfg.Key]; ok {
return TopicRegistry{}, fmt.Errorf(
"duplicate topic key %s: already registered with name %q, cannot also register name %q",
cfg.Key, existing, cfg.Name)
}

queues[cfg.Key] = cfg.Queue
topicNames[cfg.Key] = cfg.Name

Expand Down
7 changes: 6 additions & 1 deletion service/submitqueue/orchestrator/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,12 @@ func newTopicRegistry(q extqueue.Queue, subscriberName string) (consumer.TopicRe
{topickey.TopicKeySpeculate, "speculate", "orchestrator-speculate"},
{topickey.TopicKeyBuild, "build", "orchestrator-build"},
{topickey.TopicKeyBuildSignal, "buildsignal", "orchestrator-buildsignal"},
{topickey.TopicKeyMerge, "merge", "orchestrator-merge"},
// The internal merge stage is deliberately distinct from the
// runway-owned "merge" queue registered below — both in key (see
// topickey.TopicKeyMerge) and in wire name. Both topics live in the
// same registry over the same queue backend, so a shared key would
// shadow one entry and a shared name would interleave their payloads.
{topickey.TopicKeyMerge, "mergebatch", "orchestrator-merge"},
{runwaymq.TopicKeyMergeSignal, "merge-signal", "orchestrator-mergesignal"},
{topickey.TopicKeyConclude, "conclude", "orchestrator-conclude"},
}
Expand Down
6 changes: 5 additions & 1 deletion submitqueue/core/topickey/topickey.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ const (
// PublishAfter when the build has not yet reached a terminal state.
TopicKeyBuildSignal TopicKey = "buildsignal"
// TopicKeyMerge is the pipeline stage where speculated batches are published for merging.
TopicKeyMerge TopicKey = "merge"

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.

should we namespace these to say runway-merge vs just merge and same from SQ stuff to be submitqueue-merge in keys?

// The key value is deliberately NOT "merge": the orchestrator registers this internal
// stage alongside the runway-owned merge queue (runwaymq.TopicKeyMerge == "merge") in
// one registry over one queue backend, so both the key and the wire name must differ
// from runway's or the two topics collapse into each other.
TopicKeyMerge TopicKey = "mergebatch"
// TopicKeyConclude is the pipeline stage where merged requests are published for conclusion.
TopicKeyConclude TopicKey = "conclude"
// TopicKeyLog is the pipeline stage where per-request logs are written.
Expand Down
4 changes: 2 additions & 2 deletions submitqueue/orchestrator/controller/dlq/batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ func TestDLQBatchController_InterfaceAndAccessors(t *testing.T) {

c := NewDLQBatchController(zaptest.NewLogger(t).Sugar(), testScope(), store, TopicKey(topickey.TopicKeyMerge), "orchestrator-merge-dlq")

assert.Equal(t, "merge_dlq", c.Name())
assert.Equal(t, consumer.TopicKey("merge_dlq"), c.TopicKey())
assert.Equal(t, "mergebatch_dlq", c.Name())
assert.Equal(t, consumer.TopicKey("mergebatch_dlq"), c.TopicKey())
assert.Equal(t, "orchestrator-merge-dlq", c.ConsumerGroup())
}

Expand Down
Loading