Documentation
¶
Index ¶
- Constants
- Variables
- func AnalyzePlanKind(operation, definition *ast.Document, operationName string) (operationType ast.OperationType, streaming bool, error error)
- func IsMutationOrQueryRootType(typeName string) bool
- func ParseRequiredFieldsFragment(typeName, fieldName, requiredFields string, includeTypename bool) (*ast.Document, *operationreport.Report)
- func QueryPlanRequiredFieldsFragment(typeName, fieldName, requiredFields string) (*ast.Document, *operationreport.Report)
- func RequiredFieldsFragment(typeName, requiredFields string, includeTypename bool) (*ast.Document, *operationreport.Report)
- func RequiredFieldsFragmentString(typeName, fieldName, requiredFields string, includeTypename bool) (fragment string)
- func TraverseBFS(data tree.Tree[[]int]) iter.Seq2[uint, tree.Node[[]int]]
- func TreeNodeFieldRef(nodeID uint) int
- func TreeNodeID(fieldRef int) uint
- type AbstractFieldPathCollector
- type AddRequiredFieldsResult
- type ArgumentConfiguration
- type ArgumentInfo
- type ArgumentRenderConfig
- type ArgumentsConfigurations
- type Configuration
- type CostCalculator
- type CostTreeNode
- type DSHash
- type DSKeyInfo
- type DSSkip
- type DataSource
- type DataSourceBehavior
- type DataSourceConfiguration
- type DataSourceCostConfig
- type DataSourceDebugger
- type DataSourceFetchPlanner
- type DataSourceFilter
- func (f *DataSourceFilter) EnableSelectionReasons()
- func (f *DataSourceFilter) FilterDataSources(landedTo map[int]DSHash, fieldDependsOn map[int][]int) (used []DataSource, suggestions *NodeSuggestions)
- func (f *DataSourceFilter) WithMaxDataSourceCollectorsConcurrency(maxConcurrency uint) *DataSourceFilter
- type DataSourceJumpsGraph
- type DataSourceMetadata
- func (d *DataSourceMetadata) DirectiveConfigurations() *DirectiveConfigurations
- func (d *DataSourceMetadata) HasChildNode(typeName, fieldName string) bool
- func (d *DataSourceMetadata) HasChildNodeWithTypename(typeName string) bool
- func (d *DataSourceMetadata) HasExternalChildNode(typeName, fieldName string) bool
- func (d *DataSourceMetadata) HasExternalRootNode(typeName, fieldName string) bool
- func (d *DataSourceMetadata) HasRootNode(typeName, fieldName string) bool
- func (d *DataSourceMetadata) HasRootNodeWithTypename(typeName string) bool
- func (d *DataSourceMetadata) Init() error
- func (d *DataSourceMetadata) InitKeys() error
- func (d *DataSourceMetadata) InitNodesIndex()
- func (d *DataSourceMetadata) ListChildNodes() TypeFields
- func (d *DataSourceMetadata) ListRootNodes() TypeFields
- func (d *DataSourceMetadata) RequireFetchReasons() map[FieldCoordinate]struct{}
- type DataSourcePlanner
- type DataSourcePlannerConfiguration
- type DataSourcePlanningBehavior
- type DebugConfiguration
- type DirectiveConfiguration
- type DirectiveConfigurations
- type DirectivesConfigurations
- type EntityInterfaceConfiguration
- type FailedToCreatePlanningPathsError
- type FederationFieldConfiguration
- type FederationFieldConfigurations
- func (f *FederationFieldConfigurations) AppendIfNotPresent(config FederationFieldConfiguration) (added bool)
- func (f *FederationFieldConfigurations) FilterByTypeAndResolvability(typeName string, skipUnresovable bool) (out []FederationFieldConfiguration)
- func (f *FederationFieldConfigurations) FirstByTypeAndField(typeName, fieldName string) (cfg FederationFieldConfiguration, exists bool)
- func (f *FederationFieldConfigurations) HasSelectionSet(typeName, fieldName, selectionSet string) bool
- func (f *FederationFieldConfigurations) UniqueTypes() (out []string)
- type FederationInfo
- type FederationMetaData
- func (d *FederationMetaData) EntityInterfaceNames() (out []string)
- func (d *FederationMetaData) HasEntity(typeName string) bool
- func (d *FederationMetaData) HasEntityInterface(typeName string) bool
- func (d *FederationMetaData) HasInterfaceObject(typeName string) bool
- func (d *FederationMetaData) HasKeyRequirement(typeName, requiresFields string) bool
- func (d *FederationMetaData) RequiredFieldsByKey(typeName string) []FederationFieldConfiguration
- func (d *FederationMetaData) RequiredFieldsByRequires(typeName, fieldName string) (cfg FederationFieldConfiguration, exists bool)
- type FieldConfiguration
- type FieldConfigurations
- type FieldCoordinate
- type FieldLimitedVisitor
- type FieldListSize
- type FieldWeight
- type Identifyable
- type JumpCacheKey
- type KeyCondition
- type KeyIndex
- type KeyInfo
- type KeyInfoFieldPath
- type KeyJump
- type Kind
- type NodeSelectionBuilder
- type NodeSelectionResult
- type NodeSuggestion
- type NodeSuggestionDebugConfiguration
- type NodeSuggestions
- func (f *NodeSuggestions) AddItems(items ...*NodeSuggestion)
- func (f *NodeSuggestions) AddSeenField(fieldRef int)
- func (f *NodeSuggestions) HasSuggestionForPath(typeName, fieldName, path string) (dsHash DSHash, ok bool)
- func (f *NodeSuggestions) IsFieldSeen(fieldRef int) bool
- func (f *NodeSuggestions) RemoveTreeNodeChilds(fieldRef int)
- func (f *NodeSuggestions) SuggestionsForPath(typeName, fieldName, path string) (suggestions []*NodeSuggestion)
- type NodesAccess
- type NodesInfo
- type Opts
- type PathBuilder
- type PathType
- type Plan
- type Planner
- type PlannerConfiguration
- type PlannerFactory
- type PlannerPathConfiguration
- type PlannerPathType
- type QueryPlanProvider
- type RewriteResult
- type SeenKeyPath
- type SourceConnection
- type SourceConnectionType
- type SourceType
- type StaticCostVisitor
- type SubgraphRequestMinifier
- type SubscriptionConfiguration
- type SubscriptionFieldCondition
- type SubscriptionFilterCondition
- type SubscriptionResponsePlan
- type SynchronousResponsePlan
- type TypeConfiguration
- type TypeConfigurations
- type TypeField
- type TypeFields
- type Visitor
- func (v *Visitor) AllowVisitor(kind astvisitor.VisitorKind, ref int, visitor any, ...) bool
- func (v *Visitor) EnterDirective(ref int)
- func (v *Visitor) EnterDocument(operation, definition *ast.Document)
- func (v *Visitor) EnterField(ref int)
- func (v *Visitor) EnterInlineFragment(ref int)
- func (v *Visitor) EnterOperationDefinition(opRef int)
- func (v *Visitor) EnterSelectionSet(ref int)
- func (v *Visitor) LeaveDocument(_, _ *ast.Document)
- func (v *Visitor) LeaveField(fieldRef int)
- func (v *Visitor) LeaveInlineFragment(ref int)
- func (v *Visitor) LeaveSelectionSet(ref int)
Constants ¶
const ( ReasonStage1Unique = "stage1: unique" ReasonStage1SameSourceParent = "stage1: same source parent of unique node" ReasonStage2SameSourceNodeOfSelectedParent = "stage2: node on the same source as selected parent" ReasonStage2SameSourceNodeOfSelectedChild = "stage2: node on the same source as selected child" ReasonStage2SameSourceNodeOfSelectedSibling = "stage2: node on the same source as selected sibling" ReasonStage3SelectAvailableLeafNode = "stage3: select first available leaf node" ReasonStage3SelectNodeHavingPossibleChildsOnSameDataSource = "stage3: select non leaf node which have possible child selections on the same source" ReasonStage3SelectFirstAvailableRootNode = "stage3: first available root node" ReasonStage3SelectParentRootNodeWithEnabledEntityResolver = "stage3: first available parent node with enabled entity resolver" ReasonStage3SelectNodeUnderFirstParentRootNode = "stage3: node under first available parent node" ReasonStage3SelectParentNodeWhichCouldGiveKeys = "stage3: select parent node which could provide keys for the child node" ReasonKeyRequirementProvidedByPlanner = "provided by planner as required by @key" ReasonProvidesProvidedByPlanner = "@provides" )
const DefaultEnumScalarWeight = 0
const DefaultObjectWeight = 1
Variables ¶
var ( ErrFieldHasNoSelectionSet = errors.New("unexpected error: field does not have a selection set") ErrInlineFragmentHasNoSelectionSet = errors.New("unexpected error: inline fragment does not have a selection set") ErrInlineFragmentHasNoCondition = errors.New("unexpected error: inline fragment type condition does not exist") ErrNoUpstreamSchema = errors.New("unexpected error: upstream schema is not defined in DataSource") )
Functions ¶
func AnalyzePlanKind ¶
func QueryPlanRequiredFieldsFragment ¶
func QueryPlanRequiredFieldsFragment(typeName, fieldName, requiredFields string) (*ast.Document, *operationreport.Report)
func RequiredFieldsFragment ¶
func TreeNodeFieldRef ¶
func TreeNodeID ¶
Types ¶
type AbstractFieldPathCollector ¶
type AbstractFieldPathCollector struct {
*astvisitor.Walker
// contains filtered or unexported fields
}
func (*AbstractFieldPathCollector) EnterField ¶
func (v *AbstractFieldPathCollector) EnterField(ref int)
type AddRequiredFieldsResult ¶
type AddRequiredFieldsResult struct {
// contains filtered or unexported fields
}
type ArgumentConfiguration ¶
type ArgumentConfiguration struct {
Name string
SourceType SourceType
SourcePath []string
RenderConfig ArgumentRenderConfig
RenameTypeTo string
}
type ArgumentInfo ¶
type ArgumentInfo struct {
// contains filtered or unexported fields
}
type ArgumentRenderConfig ¶
type ArgumentRenderConfig string
ArgumentRenderConfig is used to determine how an argument should be rendered
const ( RenderArgumentDefault ArgumentRenderConfig = "" RenderArgumentAsArrayCSV ArgumentRenderConfig = "render_argument_as_array_csv" RenderArgumentAsGraphQLValue ArgumentRenderConfig = "render_argument_as_graphql_value" RenderArgumentAsJSONValue ArgumentRenderConfig = "render_argument_as_json_value" )
type ArgumentsConfigurations ¶
type ArgumentsConfigurations []ArgumentConfiguration
func (ArgumentsConfigurations) ForName ¶
func (a ArgumentsConfigurations) ForName(argName string) *ArgumentConfiguration
type Configuration ¶
type Configuration struct {
Logger abstractlogger.Logger
DefaultFlushIntervalMillis int64
DataSources []DataSource
MaxDataSourceCollectorsConcurrency uint
Fields FieldConfigurations
Types TypeConfigurations
EntityInterfaceNames []string
// DisableResolveFieldPositions should be set to true for testing purposes
// This setting removes position information from all fields
// In production, this should be set to false so that error messages are easier to understand
DisableResolveFieldPositions bool
// EnableOperationNamePropagation appends the operation name from nested operations
EnableOperationNamePropagation bool
CustomResolveMap map[string]resolve.CustomResolve
// Debug - configure debug options
Debug DebugConfiguration
MinifySubgraphOperations bool
// DisableIncludeInfo controls whether the planner generates resolve.FieldInfo (useful in tests).
DisableIncludeInfo bool
// DisableIncludeFieldDependencies controls whether the planner generates
// field dependency structures.
// It requires DisableIncludeInfo set to false.
DisableIncludeFieldDependencies bool
// BuildFetchReasons allows generating the FetchReasons structure for all the fields.
// It may be enabled by some other components of the engine.
// It requires DisableIncludeInfo and DisableIncludeFieldDependencies set to false.
BuildFetchReasons bool
// ValidateRequiredExternalFields validates nullable external "@requires" dependencies.
// When a subgraph entity fetch returns a null value with an error for a field set specified in
// the "@requires" directive, any following fetch that depends on it should not receive such an
// entity.
// This option requires BuildFetchReasons set to true.
ValidateRequiredExternalFields bool
// ComputeStaticCost enables static cost computation for operations.
ComputeStaticCost bool
// When the list size is unknown from directives, this value is used as a default for static cost.
StaticCostDefaultListSize int
}
type CostCalculator ¶
type CostCalculator struct {
// contains filtered or unexported fields
}
CostCalculator manages cost calculation during AST traversal
func NewCostCalculator ¶
func NewCostCalculator() *CostCalculator
NewCostCalculator creates a new cost calculator. The defaultListSize is floored to 1.
func (*CostCalculator) DebugPrint ¶
func (c *CostCalculator) DebugPrint(config Configuration, variables *astjson.Value) string
DebugPrint prints the cost tree structure for debugging purposes. It shows each node's field coordinate, costs, multipliers, and computed totals.
func (*CostCalculator) GetStaticCost ¶
func (c *CostCalculator) GetStaticCost(config Configuration, variables *astjson.Value) int
GetStaticCost returns the calculated total static cost. config should be static per process or instance. variables could change between requests.
type CostTreeNode ¶
type CostTreeNode struct {
// contains filtered or unexported fields
}
CostTreeNode represents a node in the cost calculation tree Based on IBM GraphQL Cost Specification: https://ibm.github.io/graphql-specs/cost-spec.html
type DataSource ¶
type DataSource interface {
FederationInfo
NodesInfo
DirectivesConfigurations
UpstreamSchema() (*ast.Document, bool)
PlanningBehavior() DataSourcePlanningBehavior
Id() string
Name() string
Hash() DSHash
FederationConfiguration() FederationMetaData
CreatePlannerConfiguration(logger abstractlogger.Logger, fetchConfig *objectFetchConfiguration, pathConfig *plannerPathsConfiguration, configuration *Configuration) PlannerConfiguration
// GetCostConfig returns the IBM static cost configuration for this data source
GetCostConfig() *DataSourceCostConfig
}
type DataSourceBehavior ¶
type DataSourceBehavior interface {
// DownstreamResponseFieldAlias allows the DataSourcePlanner to overwrite the response path with an alias.
// It requires DataSourcePlanningBehavior.OverrideFieldPathFromAlias to be set to true.
// This function is useful in the following scenarios:
// 1. The downstream Query doesn't contain an alias,
// 2. The path configuration rewrites the field to an existing field,
// 3. The DataSourcePlanner using an alias to the upstream.
//
// Example:
//
// type Query {
// country: Country
// countryAlias: Country
// }
//
// Both, country and countryAlias have a path in the FieldConfiguration of "country"
// In theory, they would be treated as the same field
// However, by using DownstreamResponseFieldAlias, it's possible for the DataSourcePlanner to use an alias for countryAlias.
// In this case, the response would contain both, country and countryAlias fields in the response.
// At the same time, the downstream Query would only expect the response on the path "country",
// as both country and countryAlias have a mapping to the path "country".
// The DataSourcePlanner could keep track that it rewrites the upstream query and use DownstreamResponseFieldAlias
// to indicate to the Planner to expect the response for countryAlias on the path "countryAlias" instead of "country".
DownstreamResponseFieldAlias(downstreamFieldRef int) (alias string, exists bool)
}
type DataSourceConfiguration ¶
type DataSourceConfiguration[T any] interface { DataSource CustomConfiguration() T }
func NewDataSourceConfiguration ¶
func NewDataSourceConfiguration[T any](id string, factory PlannerFactory[T], metadata *DataSourceMetadata, customConfig T) (DataSourceConfiguration[T], error)
func NewDataSourceConfigurationWithName ¶
func NewDataSourceConfigurationWithName[T any](id string, name string, factory PlannerFactory[T], metadata *DataSourceMetadata, customConfig T) (DataSourceConfiguration[T], error)
type DataSourceCostConfig ¶
type DataSourceCostConfig struct {
// Weights maps field coordinate to its weights. Cannot be on fields of interfaces.
// Location: FIELD_DEFINITION, INPUT_FIELD_DEFINITION
Weights map[FieldCoordinate]*FieldWeight
// ListSizes maps field coordinates to their respective list size configurations.
// Location: FIELD_DEFINITION
ListSizes map[FieldCoordinate]*FieldListSize
// Types maps TypeName to the weight of the object, scalar or enum definition.
// If TypeName is not present, the default value for Enums and Scalars is 0, otherwise 1.
// Weight assigned to the field or argument definitions overrides the weight of type definition.
// Location: ENUM, OBJECT, SCALAR
Types map[string]int
}
DataSourceCostConfig holds all cost configurations for a data source. This data is passed from the composition.
func NewDataSourceCostConfig ¶
func NewDataSourceCostConfig() *DataSourceCostConfig
NewDataSourceCostConfig creates a new cost config with defaults
func (*DataSourceCostConfig) EnumScalarTypeWeight ¶
func (c *DataSourceCostConfig) EnumScalarTypeWeight(enumName string) int
EnumScalarTypeWeight returns the cost for an enum or scalar types
func (*DataSourceCostConfig) ObjectTypeWeight ¶
func (c *DataSourceCostConfig) ObjectTypeWeight(name string) int
ObjectTypeWeight returns the default object cost
type DataSourceDebugger ¶
type DataSourceDebugger interface {
astvisitor.VisitorIdentifier
DebugPrint(args ...interface{})
EnableDebug()
EnableDebugQueryPlanLogging()
}
type DataSourceFetchPlanner ¶
type DataSourceFetchPlanner interface {
ConfigureFetch() resolve.FetchConfiguration
ConfigureSubscription() SubscriptionConfiguration
}
type DataSourceFilter ¶
type DataSourceFilter struct {
// contains filtered or unexported fields
}
func NewDataSourceFilter ¶
func NewDataSourceFilter(operation, definition *ast.Document, report *operationreport.Report, dataSources []DataSource, newFieldRefs map[int]struct{}) *DataSourceFilter
func (*DataSourceFilter) EnableSelectionReasons ¶
func (f *DataSourceFilter) EnableSelectionReasons()
func (*DataSourceFilter) FilterDataSources ¶
func (f *DataSourceFilter) FilterDataSources(landedTo map[int]DSHash, fieldDependsOn map[int][]int) (used []DataSource, suggestions *NodeSuggestions)
func (*DataSourceFilter) WithMaxDataSourceCollectorsConcurrency ¶
func (f *DataSourceFilter) WithMaxDataSourceCollectorsConcurrency(maxConcurrency uint) *DataSourceFilter
WithMaxDataSourceCollectorsConcurrency sets the maximum number of concurrent data source collectors
type DataSourceJumpsGraph ¶
type DataSourceJumpsGraph struct {
Jumps map[DSHash][]KeyJump
Cache map[JumpCacheKey][]SourceConnection
}
DataSourceJumpsGraph represents a graph of possible jumps between each data sources We need a way to quickly find the shortest path from one data source to another
func NewDataSourceJumpsGraph ¶
func NewDataSourceJumpsGraph(dataSources []DSHash, keysPerPath map[DSHash][]KeyInfo, typeName string) *DataSourceJumpsGraph
func (*DataSourceJumpsGraph) GetPaths ¶
func (g *DataSourceJumpsGraph) GetPaths(source DSHash, target DSHash) ([]SourceConnection, bool)
type DataSourceMetadata ¶
type DataSourceMetadata struct {
// FederationMetaData has federation-specific configuration for entity interfaces and
// the @key, @requires, @provides directives.
FederationMetaData
// RootNodes defines the nodes where the responsibility of the DataSource begins.
// RootNode is a node from which we could start a query or a subquery.
// For a federation, RootNodes contain root query type fields, entity type fields,
// and entity object fields.
RootNodes TypeFields
// ChildNodes describes additional fields, which are requested along with fields that the datasource has.
// They're always required for Graphql datasources because each field could have its own datasource.
// For a flat datasource (HTTP/REST or GRPC) we cannot request fewer fields, as we always get a full response.
// For a federation, ChildNodes contain non-entity type fields and interface type fields.
// Unions shouldn't be present in the child or root nodes.
ChildNodes TypeFields
Directives *DirectiveConfigurations
// CostConfig holds IBM static cost configuration for this data source
CostConfig *DataSourceCostConfig
// contains filtered or unexported fields
}
func (*DataSourceMetadata) DirectiveConfigurations ¶
func (d *DataSourceMetadata) DirectiveConfigurations() *DirectiveConfigurations
func (*DataSourceMetadata) HasChildNode ¶
func (d *DataSourceMetadata) HasChildNode(typeName, fieldName string) bool
func (*DataSourceMetadata) HasChildNodeWithTypename ¶
func (d *DataSourceMetadata) HasChildNodeWithTypename(typeName string) bool
func (*DataSourceMetadata) HasExternalChildNode ¶
func (d *DataSourceMetadata) HasExternalChildNode(typeName, fieldName string) bool
func (*DataSourceMetadata) HasExternalRootNode ¶
func (d *DataSourceMetadata) HasExternalRootNode(typeName, fieldName string) bool
func (*DataSourceMetadata) HasRootNode ¶
func (d *DataSourceMetadata) HasRootNode(typeName, fieldName string) bool
func (*DataSourceMetadata) HasRootNodeWithTypename ¶
func (d *DataSourceMetadata) HasRootNodeWithTypename(typeName string) bool
func (*DataSourceMetadata) Init ¶
func (d *DataSourceMetadata) Init() error
func (*DataSourceMetadata) InitKeys ¶
func (d *DataSourceMetadata) InitKeys() error
func (*DataSourceMetadata) InitNodesIndex ¶
func (d *DataSourceMetadata) InitNodesIndex()
func (*DataSourceMetadata) ListChildNodes ¶
func (d *DataSourceMetadata) ListChildNodes() TypeFields
func (*DataSourceMetadata) ListRootNodes ¶
func (d *DataSourceMetadata) ListRootNodes() TypeFields
func (*DataSourceMetadata) RequireFetchReasons ¶
func (d *DataSourceMetadata) RequireFetchReasons() map[FieldCoordinate]struct{}
type DataSourcePlanner ¶
type DataSourcePlanner[T any] interface { DataSourceFetchPlanner DataSourceBehavior Identifyable Register(visitor *Visitor, configuration DataSourceConfiguration[T], dataSourcePlannerConfiguration DataSourcePlannerConfiguration) error }
type DataSourcePlannerConfiguration ¶
type DataSourcePlannerConfiguration struct {
RequiredFields FederationFieldConfigurations
ParentPath string
PathType PlannerPathType
IsNested bool
Options plannerConfigurationOptions
FetchID int
}
func (*DataSourcePlannerConfiguration) HasRequiredFields ¶
func (c *DataSourcePlannerConfiguration) HasRequiredFields() bool
type DataSourcePlanningBehavior ¶
type DataSourcePlanningBehavior struct {
// MergeAliasedRootNodes set to true will reuse a data source for multiple root fields with aliases.
// Example:
// {
// rootField
// alias: rootField
// }
// On dynamic data sources (GraphQL, SQL) this should be set to true,
// and for static data sources (REST, static, gRPC) it should be false.
MergeAliasedRootNodes bool
// OverrideFieldPathFromAlias set to true will let the planner know
// if the response path should also be aliased.
//
// Example:
// {
// rootField
// alias: original
// }
// When true expected response will be { "rootField": ..., "alias": ... }
// When false expected response will be { "rootField": ..., "original": ... }
OverrideFieldPathFromAlias bool
// AllowPlanningTypeName set to true will allow the planner to plan __typename fields.
AllowPlanningTypeName bool
// If true then planner will rewrite the operation
// to flatten inline fragments to only the concrete types.
AlwaysFlattenFragments bool
}
DataSourcePlanningBehavior contains DataSource-specific planning flags.
type DebugConfiguration ¶
type DebugConfiguration struct {
PrintOperationTransformations bool
PrintOperationEnableASTRefs bool
PrintPlanningPaths bool
PrintQueryPlans bool
PrintNodeSuggestions bool
PrintNodeSuggestionsFilterNotSelected bool
NodeSelectionVisitor bool
ConfigurationVisitor bool
PlanningVisitor bool
DatasourceVisitor bool
}
type DirectiveConfiguration ¶
type DirectiveConfigurations ¶
type DirectiveConfigurations []DirectiveConfiguration
func NewDirectiveConfigurations ¶
func NewDirectiveConfigurations(configs []DirectiveConfiguration) *DirectiveConfigurations
func (*DirectiveConfigurations) RenameTypeNameOnMatchBytes ¶
func (d *DirectiveConfigurations) RenameTypeNameOnMatchBytes(directiveName []byte) []byte
func (*DirectiveConfigurations) RenameTypeNameOnMatchStr ¶
func (d *DirectiveConfigurations) RenameTypeNameOnMatchStr(directiveName string) string
type DirectivesConfigurations ¶
type DirectivesConfigurations interface {
DirectiveConfigurations() *DirectiveConfigurations
}
type FailedToCreatePlanningPathsError ¶
type FailedToCreatePlanningPathsError struct {
MissingPaths []string
HasFieldWaitingForDependency bool
}
func (*FailedToCreatePlanningPathsError) Error ¶
func (e *FailedToCreatePlanningPathsError) Error() string
type FederationFieldConfiguration ¶
type FederationFieldConfiguration struct {
TypeName string `json:"type_name"` // TypeName is the name of the Entity the Fragment is for
FieldName string `json:"field_name,omitempty"` // FieldName is empty for key requirements, otherwise, it is the name of the field that has requires or provides directive
SelectionSet string `json:"selection_set"` // SelectionSet is the selection set that is required for the given field (keys, requires, provides)
DisableEntityResolver bool `json:"-"` // applicable only for the keys. If true it means that the given entity could not be resolved by this key.
Conditions []KeyCondition `json:"conditions,omitempty"` // conditions stores coordinates under which we could use implicit key, while on other paths this key is not available
RemappedPaths map[string]string
// contains filtered or unexported fields
}
func (FederationFieldConfiguration) String ¶
func (f FederationFieldConfiguration) String() string
String - implements fmt.Stringer NOTE: do not change to pointer receiver, it won't work for not pointer values
type FederationFieldConfigurations ¶
type FederationFieldConfigurations []FederationFieldConfiguration
func (*FederationFieldConfigurations) AppendIfNotPresent ¶
func (f *FederationFieldConfigurations) AppendIfNotPresent(config FederationFieldConfiguration) (added bool)
func (*FederationFieldConfigurations) FilterByTypeAndResolvability ¶
func (f *FederationFieldConfigurations) FilterByTypeAndResolvability(typeName string, skipUnresovable bool) (out []FederationFieldConfiguration)
func (*FederationFieldConfigurations) FirstByTypeAndField ¶
func (f *FederationFieldConfigurations) FirstByTypeAndField(typeName, fieldName string) (cfg FederationFieldConfiguration, exists bool)
func (*FederationFieldConfigurations) HasSelectionSet ¶
func (f *FederationFieldConfigurations) HasSelectionSet(typeName, fieldName, selectionSet string) bool
func (*FederationFieldConfigurations) UniqueTypes ¶
func (f *FederationFieldConfigurations) UniqueTypes() (out []string)
type FederationInfo ¶
type FederationInfo interface {
HasKeyRequirement(typeName, requiresFields string) bool
RequiredFieldsByKey(typeName string) []FederationFieldConfiguration
RequiredFieldsByRequires(typeName, fieldName string) (cfg FederationFieldConfiguration, exists bool)
HasEntity(typeName string) bool
HasInterfaceObject(typeName string) bool
HasEntityInterface(typeName string) bool
EntityInterfaceNames() []string
}
type FederationMetaData ¶
type FederationMetaData struct {
Keys FederationFieldConfigurations
Requires FederationFieldConfigurations
Provides FederationFieldConfigurations
EntityInterfaces []EntityInterfaceConfiguration
InterfaceObjects []EntityInterfaceConfiguration
// contains filtered or unexported fields
}
func (*FederationMetaData) EntityInterfaceNames ¶
func (d *FederationMetaData) EntityInterfaceNames() (out []string)
func (*FederationMetaData) HasEntity ¶
func (d *FederationMetaData) HasEntity(typeName string) bool
func (*FederationMetaData) HasEntityInterface ¶
func (d *FederationMetaData) HasEntityInterface(typeName string) bool
func (*FederationMetaData) HasInterfaceObject ¶
func (d *FederationMetaData) HasInterfaceObject(typeName string) bool
func (*FederationMetaData) HasKeyRequirement ¶
func (d *FederationMetaData) HasKeyRequirement(typeName, requiresFields string) bool
func (*FederationMetaData) RequiredFieldsByKey ¶
func (d *FederationMetaData) RequiredFieldsByKey(typeName string) []FederationFieldConfiguration
func (*FederationMetaData) RequiredFieldsByRequires ¶
func (d *FederationMetaData) RequiredFieldsByRequires(typeName, fieldName string) (cfg FederationFieldConfiguration, exists bool)
type FieldConfiguration ¶
type FieldConfiguration struct {
TypeName string
FieldName string
// DisableDefaultMapping - instructs planner whether to use path mapping coming from Path field
DisableDefaultMapping bool // TODO: has no effect as of now, remove?
// Path - represents a json path to lookup for a field value in response json
Path []string
Arguments ArgumentsConfigurations
// UnescapeResponseJson set to true will allow fields (String,List,Object)
// to be resolved from an escaped JSON string
// e.g. {"response":"{\"foo\":\"bar\"}"} will be returned as {"foo":"bar"} when path is "response"
// This way, it is possible to resolve a JSON string as part of the response without extra String encoding of the JSON
UnescapeResponseJson bool
// HasAuthorizationRule needs to be set to true if the Authorizer should be called for this field
HasAuthorizationRule bool
SubscriptionFilterCondition *SubscriptionFilterCondition
}
type FieldConfigurations ¶
type FieldConfigurations []FieldConfiguration
func (FieldConfigurations) ForTypeField ¶
func (f FieldConfigurations) ForTypeField(typeName, fieldName string) *FieldConfiguration
type FieldCoordinate ¶
type FieldLimitedVisitor ¶
type FieldLimitedVisitor struct {
*astvisitor.Walker
// contains filtered or unexported fields
}
func (*FieldLimitedVisitor) AllowVisitor ¶
func (v *FieldLimitedVisitor) AllowVisitor(kind astvisitor.VisitorKind, ref int, visitor interface{}, skipFor astvisitor.SkipVisitors) bool
func (*FieldLimitedVisitor) EnterField ¶
func (v *FieldLimitedVisitor) EnterField(ref int)
func (*FieldLimitedVisitor) LeaveField ¶
func (v *FieldLimitedVisitor) LeaveField(ref int)
type FieldListSize ¶
type FieldListSize struct {
// AssumedSize is the default assumed size when no slicing argument is provided.
// If 0, the global default list cost is used.
AssumedSize int
// SlicingArguments are argument names that control list size (e.g., "first", "last", "limit")
// The value of these arguments will be used as the multiplier.
SlicingArguments []string
// SizedFields are contains field names in the returned object that returns lists.
// For these lists we estimate the size based on the value of the slicing arguments or AssumedSize.
SizedFields []string
// RequireOneSlicingArgument if true, at least one slicing argument must be provided.
// If false and no slicing argument is provided, AssumedSize is used.
// It is not used right now since it is required only for validation.
RequireOneSlicingArgument bool
}
FieldListSize contains parsed data from the @listSize directive for an object field.
type FieldWeight ¶
type FieldWeight struct {
// Weight is the cost of this field definition. It could be negative or zero.
// Should be used only if HasWeight is true.
Weight int
// Means that there was weight attached to the field definition.
HasWeight bool
// ArgumentWeights maps an argument name to its weight.
// Location: ARGUMENT_DEFINITION
ArgumentWeights map[string]int
}
FieldWeight defines cost configuration for a specific field of an object or input object.
type Identifyable ¶
type Identifyable interface {
astvisitor.VisitorIdentifier
}
type JumpCacheKey ¶
JumpCacheKey represents a key for the cache map
type KeyCondition ¶
type KeyCondition struct {
Coordinates []FieldCoordinate `json:"coordinates"`
FieldPath []string `json:"field_path"`
}
type KeyInfoFieldPath ¶
type KeyJump ¶
type KeyJump struct {
From DSHash
To DSHash
SelectionSet string
FieldPaths []KeyInfoFieldPath
TypeName string
}
KeyJump represents possible jump from one data source to another
type NodeSelectionBuilder ¶
type NodeSelectionBuilder struct {
// contains filtered or unexported fields
}
func NewNodeSelectionBuilder ¶
func NewNodeSelectionBuilder(config *Configuration) *NodeSelectionBuilder
func (*NodeSelectionBuilder) ResetSkipFieldRefs ¶
func (p *NodeSelectionBuilder) ResetSkipFieldRefs()
func (*NodeSelectionBuilder) SelectNodes ¶
func (p *NodeSelectionBuilder) SelectNodes(operation, definition *ast.Document, report *operationreport.Report) (out *NodeSelectionResult)
func (*NodeSelectionBuilder) SetOperationName ¶
func (p *NodeSelectionBuilder) SetOperationName(name string)
type NodeSelectionResult ¶
type NodeSelectionResult struct {
// contains filtered or unexported fields
}
type NodeSuggestion ¶
type NodeSuggestion struct {
DataSourceID string `json:"dsID"`
DataSourceName string `json:"dsName"`
DataSourceHash DSHash `json:"-"`
Path string `json:"path"`
TypeName string `json:"typeName"`
FieldName string `json:"fieldName"`
FieldRef int `json:"fieldRef"`
ParentPath string `json:"-"`
IsRootNode bool `json:"isRootNode"`
IsProvided bool `json:"isProvided"`
DisabledEntityResolver bool `json:"disabledEntityResolver"` // is true in case the node is an entity root node and all keys have disabled entity resolver
IsEntityInterfaceTypeName bool `json:"-"`
IsExternal bool `json:"isExternal"`
IsRequiredKeyField bool `json:"isRequiredKeyField"`
IsLeaf bool `json:"isLeaf"`
IsOrphan bool // if node is orphan it should not be taken into account for planning
Selected bool `json:"isSelected"`
SelectionReasons []string `json:"selectReason"`
// contains filtered or unexported fields
}
func (*NodeSuggestion) String ¶
func (n *NodeSuggestion) String() string
func (*NodeSuggestion) StringShort ¶
func (n *NodeSuggestion) StringShort() string
type NodeSuggestions ¶
type NodeSuggestions struct {
// contains filtered or unexported fields
}
func NewNodeSuggestions ¶
func NewNodeSuggestions() *NodeSuggestions
func NewNodeSuggestionsWithSize ¶
func NewNodeSuggestionsWithSize(size int) *NodeSuggestions
func (*NodeSuggestions) AddItems ¶
func (f *NodeSuggestions) AddItems(items ...*NodeSuggestion)
func (*NodeSuggestions) AddSeenField ¶
func (f *NodeSuggestions) AddSeenField(fieldRef int)
func (*NodeSuggestions) HasSuggestionForPath ¶
func (f *NodeSuggestions) HasSuggestionForPath(typeName, fieldName, path string) (dsHash DSHash, ok bool)
func (*NodeSuggestions) IsFieldSeen ¶
func (f *NodeSuggestions) IsFieldSeen(fieldRef int) bool
func (*NodeSuggestions) RemoveTreeNodeChilds ¶
func (f *NodeSuggestions) RemoveTreeNodeChilds(fieldRef int)
func (*NodeSuggestions) SuggestionsForPath ¶
func (f *NodeSuggestions) SuggestionsForPath(typeName, fieldName, path string) (suggestions []*NodeSuggestion)
type NodesAccess ¶
type NodesAccess interface {
ListRootNodes() TypeFields
ListChildNodes() TypeFields
}
type NodesInfo ¶
type NodesInfo interface {
HasRootNode(typeName, fieldName string) bool
HasExternalRootNode(typeName, fieldName string) bool
HasRootNodeWithTypename(typeName string) bool
HasChildNode(typeName, fieldName string) bool
HasExternalChildNode(typeName, fieldName string) bool
HasChildNodeWithTypename(typeName string) bool
RequireFetchReasons() map[FieldCoordinate]struct{}
}
type Opts ¶
type Opts func(*_opts)
func IncludeQueryPlanInResponse ¶
func IncludeQueryPlanInResponse() Opts
type PathBuilder ¶
type PathBuilder struct {
// contains filtered or unexported fields
}
func NewPathBuilder ¶
func NewPathBuilder(config *Configuration) *PathBuilder
func (*PathBuilder) CreatePlanningPaths ¶
func (p *PathBuilder) CreatePlanningPaths(operation, definition *ast.Document, report *operationreport.Report) []PlannerConfiguration
func (*PathBuilder) SetOperationName ¶
func (p *PathBuilder) SetOperationName(name string)
func (*PathBuilder) SetSelectionsConfig ¶
func (p *PathBuilder) SetSelectionsConfig(selectionsConfig *NodeSelectionResult)
type Plan ¶
type Plan interface {
PlanKind() Kind
SetFlushInterval(interval int64)
GetStaticCostCalculator() *CostCalculator
SetStaticCostCalculator(calc *CostCalculator)
}
type Planner ¶
type Planner struct {
// contains filtered or unexported fields
}
func NewPlanner ¶
func NewPlanner(config Configuration) (*Planner, error)
NewPlanner creates a new Planner from the Configuration.
NOTE: All stateful DataSources should be initiated with the same context.Context object provided to the PlannerFactory. The context.Context object is used to determine the lifecycle of stateful DataSources. It's important to note that stateful DataSources must be closed when they are no longer being used.
Stateful DataSources could be those that initiate a WebSocket connection to an origin, a database client, a streaming client, etc... To ensure that there are no memory leaks, it's therefore important to add a cancel func or timeout to the context.Context. At the time when the resolver and all operations should be garbage collected, ensure to first cancel or timeout the ctx object. If you don't cancel the context.Context, the goroutines will run indefinitely and there's no reference left to stop them.
type PlannerConfiguration ¶
type PlannerConfiguration interface {
DataSourceBehavior
PlannerPathConfiguration
ObjectFetchConfiguration() *objectFetchConfiguration
DataSourceConfiguration() DataSource
RequiredFields() *FederationFieldConfigurations
Debugger() (d DataSourceDebugger, ok bool)
Planner() any
Register(visitor *Visitor) error
}
type PlannerFactory ¶
type PlannerFactory[DataSourceSpecificConfiguration any] interface { // Planner creates a new DataSourcePlanner Planner(logger abstractlogger.Logger) DataSourcePlanner[DataSourceSpecificConfiguration] // Context returns the execution context of the factory // For stateful datasources, the factory should contain cancellable global execution context // This method serves as a flag that factory should have a context Context() context.Context UpstreamSchema(dataSourceConfig DataSourceConfiguration[DataSourceSpecificConfiguration]) (*ast.Document, bool) PlanningBehavior() DataSourcePlanningBehavior }
PlannerFactory creates concrete DataSourcePlanner's. For stateful datasources, the factory should contain execution context Once the context gets canceled, all stateful DataSources must close their connections and cleanup themselves.
type PlannerPathConfiguration ¶
type PlannerPathConfiguration interface {
ForEachPath(each func(*pathConfiguration) (shouldBreak bool))
RemoveLeafFragmentPaths() (hasRemovals bool)
ParentPath() string
AddPath(configuration pathConfiguration)
IsNestedPlanner() bool
HasPath(path string) bool
HasPathWithFieldRef(fieldRef int) bool
HasFragmentPath(fragmentRef int) bool
ShouldWalkFieldsOnPath(path string, typeName string) bool
HasParent(parent string) bool
}
type PlannerPathType ¶
type PlannerPathType int
const ( PlannerPathObject PlannerPathType = iota PlannerPathArrayItem PlannerPathNestedInArray )
type QueryPlanProvider ¶
type QueryPlanProvider interface {
IncludeQueryPlanInFetchConfiguration()
}
type RewriteResult ¶
type RewriteResult struct {
// contains filtered or unexported fields
}
type SeenKeyPath ¶
type SourceConnection ¶
type SourceConnection struct {
Source DSHash
Target DSHash
Jumps []KeyJump
Type SourceConnectionType
}
type SourceConnectionType ¶
type SourceConnectionType int
const ( SourceConnectionTypeDirect SourceConnectionType = iota SourceConnectionTypeIndirect )
type SourceType ¶
type SourceType string
SourceType is used to determine the source of an argument
const ( ObjectFieldSource SourceType = "object_field" FieldArgumentSource SourceType = "field_argument" )
type StaticCostVisitor ¶
type StaticCostVisitor struct {
Walker *astvisitor.Walker
// AST documents - set before walking
Operation *ast.Document
Definition *ast.Document
// contains filtered or unexported fields
}
StaticCostVisitor builds the cost tree during AST traversal. It is registered on the same walker as the planning Visitor and uses data from the planning visitor (fieldPlanners, planners) to determine which data sources are responsible for each field.
func NewStaticCostVisitor ¶
func NewStaticCostVisitor(walker *astvisitor.Walker, operation, definition *ast.Document) *StaticCostVisitor
NewStaticCostVisitor creates a new cost tree visitor
func (*StaticCostVisitor) EnterField ¶
func (v *StaticCostVisitor) EnterField(fieldRef int)
EnterField creates a partial cost node when entering a field. The node is filled in full in the LeaveField when fieldPlanners data is available.
func (*StaticCostVisitor) LeaveField ¶
func (v *StaticCostVisitor) LeaveField(fieldRef int)
LeaveField fills DataSource hashes for the current node and pop it from the cost stack.
type SubgraphRequestMinifier ¶
type SubgraphRequestMinifier interface {
EnableSubgraphRequestMinifier()
}
type SubscriptionConfiguration ¶
type SubscriptionConfiguration struct {
Input string
Variables resolve.Variables
DataSource resolve.SubscriptionDataSource
PostProcessing resolve.PostProcessingConfiguration
QueryPlan *resolve.QueryPlan
}
type SubscriptionFilterCondition ¶
type SubscriptionFilterCondition struct {
And []SubscriptionFilterCondition
Or []SubscriptionFilterCondition
Not *SubscriptionFilterCondition
In *SubscriptionFieldCondition
}
type SubscriptionResponsePlan ¶
type SubscriptionResponsePlan struct {
Response *resolve.GraphQLSubscription
FlushInterval int64
StaticCostCalculator *CostCalculator
}
func (*SubscriptionResponsePlan) GetStaticCostCalculator ¶
func (s *SubscriptionResponsePlan) GetStaticCostCalculator() *CostCalculator
func (*SubscriptionResponsePlan) PlanKind ¶
func (*SubscriptionResponsePlan) PlanKind() Kind
func (*SubscriptionResponsePlan) SetFlushInterval ¶
func (s *SubscriptionResponsePlan) SetFlushInterval(interval int64)
func (*SubscriptionResponsePlan) SetStaticCostCalculator ¶
func (s *SubscriptionResponsePlan) SetStaticCostCalculator(c *CostCalculator)
type SynchronousResponsePlan ¶
type SynchronousResponsePlan struct {
Response *resolve.GraphQLResponse
FlushInterval int64
StaticCostCalculator *CostCalculator
}
func (*SynchronousResponsePlan) GetStaticCostCalculator ¶
func (s *SynchronousResponsePlan) GetStaticCostCalculator() *CostCalculator
func (*SynchronousResponsePlan) PlanKind ¶
func (*SynchronousResponsePlan) PlanKind() Kind
func (*SynchronousResponsePlan) SetFlushInterval ¶
func (s *SynchronousResponsePlan) SetFlushInterval(interval int64)
func (*SynchronousResponsePlan) SetStaticCostCalculator ¶
func (s *SynchronousResponsePlan) SetStaticCostCalculator(c *CostCalculator)
type TypeConfiguration ¶
type TypeConfiguration struct {
TypeName string
// RenameTo modifies the TypeName
// so that a downstream Operation can contain a different TypeName than the upstream Schema
// e.g. if the downstream Operation contains { ... on Human_api { height } }
// the upstream Operation can be rewritten to { ... on Human { height }}
// by setting RenameTo to Human
// This way, Types can be suffixed / renamed in downstream Schemas while keeping the contract with the upstream ok
RenameTo string
}
type TypeConfigurations ¶
type TypeConfigurations []TypeConfiguration
func (*TypeConfigurations) RenameTypeNameOnMatchBytes ¶
func (t *TypeConfigurations) RenameTypeNameOnMatchBytes(typeName []byte) []byte
func (*TypeConfigurations) RenameTypeNameOnMatchStr ¶
func (t *TypeConfigurations) RenameTypeNameOnMatchStr(typeName string) string
type TypeFields ¶
type TypeFields []TypeField
type Visitor ¶
type Visitor struct {
Operation, Definition *ast.Document
Walker *astvisitor.Walker
Importer astimport.Importer
Config Configuration
OperationName string
// contains filtered or unexported fields
}
Visitor creates the shape of resolve.GraphQLResponse.
func (*Visitor) AllowVisitor ¶
func (v *Visitor) AllowVisitor(kind astvisitor.VisitorKind, ref int, visitor any, skipFor astvisitor.SkipVisitors) bool
func (*Visitor) EnterDirective ¶
func (*Visitor) EnterDocument ¶
func (*Visitor) EnterField ¶
func (*Visitor) EnterInlineFragment ¶
func (*Visitor) EnterOperationDefinition ¶
func (*Visitor) EnterSelectionSet ¶
func (*Visitor) LeaveDocument ¶
func (*Visitor) LeaveField ¶
func (*Visitor) LeaveInlineFragment ¶
func (*Visitor) LeaveSelectionSet ¶
Source Files
¶
- abstract_selection_rewriter.go
- abstract_selection_rewriter_helpers.go
- abstract_selection_rewriter_info.go
- analyze_plan_kind.go
- configuration.go
- datasource_configuration.go
- datasource_filter_collect_nodes_visitor.go
- datasource_filter_node_suggestions.go
- datasource_filter_resolvable_visitor.go
- datasource_filter_visitor.go
- federation_metadata.go
- key_fields_visitor.go
- minifier.go
- node_selection_builder.go
- node_selection_visitor.go
- path_builder.go
- path_builder_visitor.go
- plan.go
- planner.go
- planner_configuration.go
- provides_fields_visitor.go
- required_fields_visitor.go
- source_connection_graph.go
- static_cost.go
- static_cost_visitor.go
- type_field.go
- visitor.go