Compare commits

..

1 Commits

Author SHA1 Message Date
Dean Wenstrand
8441bb12e9 Select stream.id in upload-status operations so the cache stays normalized
All checks were successful
Tests / Tests (pull_request) Successful in 11s
UploadStreamWithDetails and the editUploadStream response selected
stream fields without id. Apollo cannot normalize an object with no id
selected, so every upload-service poll rewrote VideoGQL.stream as an
anonymous inline object — clobbering the id that feed/detail queries
select. Their cache reads went partial and useQuery silently fell back
to the last network result, rendered as the home feed collapsing to
the first page (and bouncing the viewport) whenever an upload was
polling.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 19:27:25 -07:00
4 changed files with 15087 additions and 5916 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -85,53 +85,3 @@ query ComputePotAim(
occludingBallIds
}
}
fragment PositionShotCandidate on PositionShotCandidateGQL {
strike {
v0
phi
theta
a
b
}
cueFinalPosition
inTargetArea
distanceToTargetArea
robustness
potted
scratched
projection {
trajectories {
ballId
points {
time
position
}
}
events {
eventType
time
ballIds
position
}
finalState {
ballId
position
}
pottedBallIds
}
}
query SuggestPositionShot($suggestionInput: SuggestPositionShotInputGQL!) {
suggestPositionShot(suggestionInput: $suggestionInput) {
achievable
evaluatedCount
successfulCount
best {
...PositionShotCandidate
}
alternates {
...PositionShotCandidate
}
}
}

View File

@@ -48,6 +48,7 @@ mutation GetUploadLink($videoId: Int!, $segmentIndex: Int!) {
}
}
stream {
id
uploadCompletionCursor
}
}
@@ -127,6 +128,7 @@ fragment UploadStreamWithDetails on VideoGQL {
name
startTime
stream {
id
isCompleted
lastIntendedSegmentBound
uploadCompletionCursor

View File

@@ -81,9 +81,6 @@ type Query {
targetBallId: Int!
pocket: PocketIdentifier!
): PotAimGQL!
suggestPositionShot(
suggestionInput: SuggestPositionShotInputGQL!
): PositionSuggestionGQL!
getOrderedShots(
filterInput: FilterInput!
ids: [Int!] = null
@@ -1222,44 +1219,6 @@ type PotAimGQL {
occludingBallIds: [Int!]!
}
type PositionSuggestionGQL {
achievable: Boolean!
best: PositionShotCandidateGQL
alternates: [PositionShotCandidateGQL!]!
evaluatedCount: Int!
successfulCount: Int!
}
type PositionShotCandidateGQL {
strike: CueStrikeGQL!
cueFinalPosition: [Float!]!
inTargetArea: Boolean!
distanceToTargetArea: Float!
robustness: Int!
potted: Boolean!
scratched: Boolean!
projection: ShotProjectionGQL
}
type CueStrikeGQL {
v0: Float!
phi: Float!
theta: Float!
a: Float!
b: Float!
}
input SuggestPositionShotInputGQL {
cueBallId: Int!
targetBallId: Int!
pocket: PocketIdentifier!
targetArea: [[Float!]!]!
balls: [SimulationBallStateInputGQL!] = null
b64Image: String = null
useHomography: HomographyInputGQL = null
tableSize: Float = null
}
type GetShotsResult {
shots: [ShotGQL!]!
count: Int
@@ -1942,7 +1901,6 @@ input VideoMetadataInput {
clientUploadStatus: ClientUploadStatusEnum = null
resolution: VideoResolution = null
framesPerSecond: Float = null
homographyBackend: HomographyBackendGQL = null
}
input VideoResolution {
@@ -1950,11 +1908,6 @@ input VideoResolution {
height: Int!
}
enum HomographyBackendGQL {
CLASSIC
TABLENET
}
type GetUploadLinkReturn {
value: UploadLinkGetUploadLinkErrors!
stream: UploadStreamGQL