Add ListTeamsIncludingProperties for batched team metadata reads - #643
Open
saditya370 wants to merge 1 commit into
Open
Add ListTeamsIncludingProperties for batched team metadata reads#643saditya370 wants to merge 1 commit into
saditya370 wants to merge 1 commit into
Conversation
saditya370
force-pushed
the
aditya/OPS-27/list-teams-including-properties
branch
from
August 25, 2026 12:22
d3deb22 to
0909c68
Compare
Team.Properties is excluded from generated queries with `graphql:"-"`, so a caller needing properties for many teams pays one extra request per team. Add a TeamWithProperties type that embeds Team and redeclares Properties with a graphql tag, selecting the connection inline, plus ListTeamsIncludingProperties which returns every team with its tags and properties at one request per page. Tags and memberships are completed by the existing Team.Hydrate; a team holding more than 100 properties is topped up on its own rather than charging every team an extra request. Purely additive. Team.Properties, ListTeams, and Hydrate are untouched, so existing callers execute identical code paths.
saditya370
force-pushed
the
aditya/OPS-27/list-teams-including-properties
branch
from
August 25, 2026 12:24
0909c68 to
3021749
Compare
| // | ||
| // The inlined properties connection is selected without pagination arguments, so the API | ||
| // returns its first 100 entries; any team holding more than that is topped up on its own. | ||
| func (client *Client) ListTeamsIncludingProperties(variables *PayloadVariables) ([]TeamWithProperties, error) { |
Contributor
There was a problem hiding this comment.
I don't think that this solution is very composable. If we want to extend what teams returns, we'll have to deprecate this and replace it with something else. I'll come up with a recommendation.
Contributor
There was a problem hiding this comment.
I think that instead of doing ListTeamsIncludingProperties or hydrating properties per team, we can remove the properties opt out & hydrate them per page instead of per team.
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.
Problem
Team.Propertiesis taggedgraphql:"-", so it is never selected by generatedqueries. Any caller that wants properties for a list of teams has to call
(*Team).GetPropertiesper team.For the Terraform provider's
opslevel_teamsdata source that is one requestper team. Measured against a 263-team account, the per-team approach issued
~266 requests and took 26 seconds, close enough to the provider's 30s
client timeout that one of two runs died mid-read. It is not viable at
customer scale.
Solution
ListTeamsIncludingPropertiesselects the properties connection inlinealongside the team list, so listing every team costs one request per page
instead of one per team. Same account, same data: 3 requests, under a
second end to end through the provider.
TeamWithPropertiesembedsTeamand redeclaresPropertieswith a graphqltag. Go field shadowing means the embedded
graphql:"-"field is skipped andours is selected, so the query asks for
propertiesexactly once. That issubtle enough to be worth a guard, so
TestListTeamsIncludingPropertiesasserts the full constructed query string.
Because the test registers a single request and the autopilot harness fails
on any request it was not told to expect, a per-team fan-out regression would
surface as an unregistered call rather than silently passing.
Tags and memberships are completed by the existing
Team.Hydrate, which issuesno request unless a connection actually spills past its first page. The inlined
properties connection is selected without pagination arguments, so the API
returns its first 100; a team holding more than that is topped up individually.
Alternatives considered
graphql:"-"fromTeam.Properties. Simplest, but it would makeevery existing Team query heavier for every consumer. Rejected.
to an opslevel-go internal modeling decision and leaves other consumers
(
opslevel-mcpcallsListTeamstoo) to reinvent it. Rejected in favour offixing it at the client layer.
ListTeamsWithProperties— every existingListXWith*in this repo means filtered by (ListTeamsWithManager,ListServicesWithTier), so that name would read as "teams that haveproperties".
No regression by construction: the diff is 146 insertions and 0 deletions.
Not one existing line changed.
Noted but not fixed here
ListTeamsonly callsHydrateon nodes from its recursive call, so teams onthe first page are never hydrated. With a default page size of 500, that
means most accounts get no hydration at all:
ResponsibilitiesstaysHTML-escaped and
TotalCountstays 0. The same pattern appears in 17 placesacross 5 files. Filing separately, since fixing it changes observable values
for every existing consumer and does not belong in an additive PR.
Checklist