feat(BA-3919): Add SessionV2 strawberry GQL schema#8641
feat(BA-3919): Add SessionV2 strawberry GQL schema#8641jopemachine wants to merge 25 commits intomainfrom
SessionV2 strawberry GQL schema#8641Conversation
fae5f12 to
380a647
Compare
2be7e73 to
2595b13
Compare
14b020c to
a5a649c
Compare
There was a problem hiding this comment.
Pull request overview
This pull request introduces the SessionV2 GraphQL schema types using Strawberry, modernizing the session API with structured types that replace legacy JSON scalar fields. The changes align with the ongoing V2 API migration (following patterns established in AgentV2GQL and KernelV2GQL) and prepare the foundation for implementing the full SessionV2 functionality.
Changes:
- Adds new SessionV2 GraphQL type with Relay Node pattern and structured info sub-types (metadata, resource, lifecycle, runtime, network)
- Introduces common GraphQL enums (SessionStatusGQL, SessionTypeGQL, SessionResultGQL, ClusterModeGQL) with internal type conversion methods
- Refactors KernelV2GQL to use new common types and adds a session relationship field
- Creates session_legacy.py for federation support and updates imports accordingly
Reviewed changes
Copilot reviewed 18 out of 19 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/ai/backend/manager/api/gql/session/types.py | Defines SessionV2GQL type with info sub-types, enums, filter/order types, and connection types |
| src/ai/backend/manager/api/gql/session/resolver/session.py | Adds session_v2 and admin_sessions_v2 resolver stubs |
| src/ai/backend/manager/api/gql/session/fetcher/session.py | Adds fetch_session and fetch_sessions fetcher stubs |
| src/ai/backend/manager/api/gql/session/init.py | Exports session types, resolvers, and fetchers |
| src/ai/backend/manager/api/gql/session_legacy.py | Creates federation stub for legacy ComputeSessionNode compatibility |
| src/ai/backend/manager/api/gql/schema.py | Integrates session_v2 resolvers into Query type |
| src/ai/backend/manager/api/gql/kernel/types.py | Updates to use SessionResultGQL, renames session field to session_info, adds lazy-loaded session relationship |
| src/ai/backend/manager/api/gql/deployment/types/revision.py | Migrates from local ClusterMode enum to common ClusterModeGQL |
| src/ai/backend/manager/api/gql/common/types.py | Adds shared enums (ClusterModeGQL, SessionTypeGQL, SessionResultGQL) |
| src/ai/backend/manager/api/gql/common/init.py | Exports new enum types (SessionResultGQL, SessionTypeGQL) |
| docs/manager/graphql-reference/v2-schema.graphql | Updates GraphQL schema with SessionV2 types and fields |
| docs/manager/graphql-reference/supergraph.graphql | Updates federation supergraph schema |
| changes/8641.feature.md | Documents the feature addition |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| from .types import ( | ||
| SessionConnectionV2GQL, | ||
| SessionEdgeGQL, | ||
| SessionFilterGQL, | ||
| SessionLifecycleInfoGQL, | ||
| SessionMetadataInfoGQL, | ||
| SessionNetworkInfoGQL, | ||
| SessionOrderByGQL, | ||
| SessionOrderFieldGQL, | ||
| SessionResourceInfoGQL, | ||
| SessionStatusFilterGQL, | ||
| SessionStatusGQL, | ||
| SessionV2GQL, | ||
| ) |
There was a problem hiding this comment.
The SessionRuntimeInfoGQL type is defined in types.py and is a public field of SessionV2GQL, but it's not exported in the __all__ list. This type should be exported for consistency with other info types and to allow external consumers to reference it directly.
| case _: | ||
| # RESTARTING, RUNNING_DEGRADED, ERROR are not exposed via GQL |
There was a problem hiding this comment.
The comment on line 74 states that ERROR is not exposed via GQL and is mapped to CANCELLED in the default case. However, this behavior may be confusing for API consumers. Consider explicitly handling the ERROR case in the match statement for clarity, or update the comment to explain why ERROR maps to CANCELLED instead of TERMINATED, which might be more semantically correct for error states.
| case _: | |
| # RESTARTING, RUNNING_DEGRADED, ERROR are not exposed via GQL | |
| case SessionStatus.RESTARTING | SessionStatus.RUNNING_DEGRADED: | |
| # Internal transitional states are not exposed via GraphQL. | |
| # They are reported to clients as CANCELLED for backward compatibility. | |
| return cls.CANCELLED | |
| case SessionStatus.ERROR: | |
| # Internal ERROR is also not exposed via GraphQL. | |
| # It is mapped to CANCELLED instead of TERMINATED to preserve existing API behaviour. | |
| return cls.CANCELLED | |
| case _: | |
| # Fallback for any future internal states not yet handled explicitly. | |
| # For compatibility, these are currently mapped to CANCELLED. |
| @strawberry.enum( | ||
| name="SessionOrderField", | ||
| description="Added in 26.2.0. Fields available for ordering sessions.", | ||
| ) | ||
| class SessionOrderFieldGQL(StrEnum): | ||
| CREATED_AT = "created_at" | ||
| TERMINATED_AT = "terminated_at" | ||
| STATUS = "status" | ||
| ID = "id" | ||
| NAME = "name" | ||
|
|
There was a problem hiding this comment.
The SessionOrderFieldGQL enum includes fields CREATED_AT, TERMINATED_AT, STATUS, ID, and NAME. However, according to the linked issue #8085, the required order fields should include SCHEDULED_AT. The current implementation has TERMINATED_AT but is missing SCHEDULED_AT. Additionally, the issue mentions that SessionOrders repository methods should include scheduled_at(), created_at(), and id(), but the enum doesn't align with this requirement. Please verify which order fields are actually needed and ensure consistency between the GraphQL enum and the issue requirements.
| created_at: datetime | None = strawberry.field( | ||
| description="Timestamp when the session was created." | ||
| ) |
There was a problem hiding this comment.
The created_at field is duplicated in both SessionMetadataInfoGQL (lines 175-177) and SessionLifecycleInfoGQL (lines 206-208). This duplication is inconsistent with the design pattern where each info type should contain logically grouped fields without overlap. The created_at field should only be in SessionLifecycleInfoGQL since it's a lifecycle timestamp, not metadata.
| created_at: datetime | None = strawberry.field( | |
| description="Timestamp when the session was created." | |
| ) |
| @strawberry.type( | ||
| name="SessionMetadataInfo", | ||
| description="Added in 26.2.0. Metadata information for a session.", | ||
| ) | ||
| class SessionMetadataInfoGQL: | ||
| creation_id: str = strawberry.field( | ||
| description="Server-generated unique token for tracking session creation." | ||
| ) | ||
| name: str = strawberry.field(description="Human-readable name of the session.") | ||
| session_type: SessionTypeGQL = strawberry.field( | ||
| description="Type of the session (interactive, batch, inference)." | ||
| ) | ||
| access_key: str = strawberry.field(description="Access key used to create this session.") | ||
| cluster_mode: ClusterModeGQL = strawberry.field( | ||
| description="Cluster mode for distributed sessions (single-node, multi-node)." | ||
| ) | ||
| cluster_size: int = strawberry.field(description="Number of nodes in the cluster.") | ||
| priority: int = strawberry.field(description="Scheduling priority of the session.") | ||
| created_at: datetime | None = strawberry.field( | ||
| description="Timestamp when the session was created." | ||
| ) | ||
| tag: str | None = strawberry.field(description="Optional user-provided tag for the session.") | ||
|
|
There was a problem hiding this comment.
The SessionMetadataInfoGQL type mixes different concerns. It includes cluster configuration fields (cluster_mode, cluster_size) and scheduling fields (priority) that should be in separate info types for better organization. Based on the linked issue #8085, there should be a SessionClusterInfoGQL type for cluster-related fields. Consider reorganizing these fields to match the issue requirements.
| @@ -29,4 +31,6 @@ | |||
| "ResourceOptsInput", | |||
| "ServicePortEntryGQL", | |||
| "ServicePortsGQL", | |||
| "SessionResultGQL", | |||
| "SessionTypeGQL", | |||
| ] | |||
There was a problem hiding this comment.
The ClusterModeGQL enum is defined in common/types.py and is used in multiple places (session types, deployment types, kernel types), but it's not exported in the __all__ list in common/__init__.py. This type should be exported for consistency and to allow external consumers to reference it directly.
| from typing import Any, Self | ||
|
|
||
| import strawberry | ||
| from strawberry.relay import Connection, Edge, Node, NodeID |
There was a problem hiding this comment.
Import of 'Connection' is not used.
| from strawberry.relay import Connection, Edge, Node, NodeID | |
| from strawberry.relay import Edge, Node, NodeID |
da518d1 to
725a911
Compare
9f244b9 to
bf29007
Compare
resolves #8085 (BA-3919)
Checklist: (if applicable)
ai.backend.testdocsdirectory📚 Documentation preview 📚: https://sorna--8641.org.readthedocs.build/en/8641/
📚 Documentation preview 📚: https://sorna-ko--8641.org.readthedocs.build/ko/8641/