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
1 change: 1 addition & 0 deletions submitqueue/entity/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ go_library(
"queue_config.go",
"request.go",
"request_log.go",
"request_summary.go",
"speculation_tree.go",
],
importpath = "github.com/uber/submitqueue/submitqueue/entity",
Expand Down
70 changes: 70 additions & 0 deletions submitqueue/entity/request_summary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) 2025 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package entity

// RequestSummary is the gateway-owned materialized current view of a request.
// RequestID is exposed as sqid by the gateway API.
type RequestSummary struct {
// RequestID is the globally unique request identifier.
RequestID string
// Queue is the queue supplied at receipt.
Queue string
// ChangeURIs are the change URIs supplied at receipt in caller order.
ChangeURIs []string
// ReceivedAtMs is the immutable receipt timestamp in Unix milliseconds.
ReceivedAtMs int64
// Status is the current customer-facing request status.
Status RequestStatus
// RequestVersion is the orchestrator request version carried by the winning log entry, or zero when unavailable.
RequestVersion int32
// StatusTimestampMs is the timestamp of the winning log entry in Unix milliseconds.
StatusTimestampMs int64
// ProjectionVersion is the optimistic-lock version of this materialized view.
ProjectionVersion int32

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.

do we want to call just Version for this one

// LastError is the error associated with the current status, or empty when absent.
LastError string
// Metadata is display and debugging metadata associated with the current status.
Metadata map[string]string
}

// RequestQueueSummary is the queue-ordered projection returned by List.
type RequestQueueSummary struct {
// RequestID is the globally unique request identifier.
RequestID string
// Queue is the queue supplied at receipt.
Queue string
// ChangeURIs are the change URIs supplied at receipt in caller order.
ChangeURIs []string
// ReceivedAtMs is the immutable receipt timestamp in Unix milliseconds.
ReceivedAtMs int64
// Status is the current customer-facing request status.
Status RequestStatus
// ProjectionVersion is copied from the authoritative RequestSummary and guards stale projection writers.
ProjectionVersion int32

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.

Version?

// LastError is the error associated with the current status, or empty when absent.
LastError string
// Metadata is display and debugging metadata associated with the current status.
Metadata map[string]string
}

// RequestURI maps one change URI to one received request.
type RequestURI struct {
// ChangeURI is the exact canonical URI supplied at receipt.
ChangeURI string
// ReceivedAtMs is the immutable receipt timestamp in Unix milliseconds.
ReceivedAtMs int64
// RequestID is the globally unique request identifier.
RequestID string
}
19 changes: 19 additions & 0 deletions submitqueue/extension/storage/mysql/schema/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,22 @@ As the `batch` table grows, the secondary index will grow with it, increasing st

The `change` table records per-URI claims by in-flight requests. `request_id` is part of the primary key so that concurrent claims on the same URI by different requests coexist as distinct rows — a same-request retry collides on the PK and is a no-op (`INSERT IGNORE`), while a different-request claim is a new row that `GetByURI` surfaces for overlap detection. `queue` leads the key so queue-scoped lookups are primary-key-prefix scans and the table is shardable by queue.

## Gateway request read model

The gateway request read model uses three additive tables and requires no alteration of existing tables. Deployments create these tables empty and populate them only for requests received after rollout; historical request logs and orchestrator working tables are intentionally not backfilled.

### `request_summary`

`request_summary` is keyed by `request_id` and serves direct Status lookup. It stores immutable receipt context plus the current materialized request-log winner and its optimistic-lock projection version.

### `request_summary_by_queue`

`request_summary_by_queue` is keyed by `(queue, received_at_ms, request_id)`. This key covers the List predicate, descending sort, and keyset continuation for one bounded receipt-time window without a secondary index. The row duplicates the complete List response so one page is served by one range scan rather than one follow-up read per request ID.

### `request_by_change_uri`

`request_by_change_uri` is keyed by `(change_uri, received_at_ms, request_id)` and serves bounded newest-first Status lookup by change URI. The gateway reads at most 101 mappings to enforce the API maximum of 100 results without silently truncating.

### JSON collections

`change_uris` and `metadata` are non-null application values. MySQL JSON columns can contain the JSON value `null` despite `NOT NULL`, so stores normalize nil slices and maps to empty values on both write and read.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS request_by_change_uri (

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.

change_uri_request_mapping?

change_uri VARCHAR(255) NOT NULL,
received_at_ms BIGINT NOT NULL,
request_id VARCHAR(255) NOT NULL,
PRIMARY KEY (change_uri, received_at_ms, request_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
13 changes: 13 additions & 0 deletions submitqueue/extension/storage/mysql/schema/request_summary.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CREATE TABLE IF NOT EXISTS request_summary (
request_id VARCHAR(255) NOT NULL,
queue VARCHAR(255) NOT NULL,
change_uris JSON NOT NULL,
received_at_ms BIGINT NOT NULL,
status VARCHAR(64) NOT NULL,
request_version INT NOT NULL,
status_timestamp_ms BIGINT NOT NULL,
projection_version INT NOT NULL,
last_error TEXT NOT NULL,
metadata JSON NOT NULL,
PRIMARY KEY (request_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS request_summary_by_queue (
queue VARCHAR(255) NOT NULL,
received_at_ms BIGINT NOT NULL,
request_id VARCHAR(255) NOT NULL,
change_uris JSON NOT NULL,
status VARCHAR(64) NOT NULL,
projection_version INT NOT NULL,
last_error TEXT NOT NULL,
metadata JSON NOT NULL,
PRIMARY KEY (queue, received_at_ms, request_id)

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 request_id be part of it?

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Loading