MCPcopy Index your code
hub / github.com/dgraph-io/dgraph / resolveCustomField

Method resolveCustomField

query/outputnode_graphql.go:737–1002  ·  view source on GitHub ↗

resolveCustomField resolves the @custom childField by making an external HTTP request and then updates the fastJson tree with results of that HTTP request. It accepts the following arguments: - childField: the @custom field which needs to be resolved - parentNodeHeads: a list of head pointers to the

(childField gqlSchema.Field,
	parentNodeHeads []fastJsonNode, wg *sync.WaitGroup)

Source from the content-addressed store, hash-verified

735// https://medium.com/@_orcaman/when-too-much-concurrency-slows-you-down-golang-9c144ca305a
736// - worry about path in errors and how to deal with them, specially during completion step
737func (genc *graphQLEncoder) resolveCustomField(childField gqlSchema.Field,
738 parentNodeHeads []fastJsonNode, wg *sync.WaitGroup) {
739 defer wg.Done() // signal when this goroutine finishes execution
740
741 fconf, err := childField.CustomHTTPConfig()
742 if err != nil {
743 genc.errCh <- x.GqlErrorList{childField.GqlErrorf(nil, "%s", err.Error())}
744 return
745 }
746 // for resolving a custom field, we need to carry out following steps:
747 // 1: Find the requiredFields data for uniqueParents from all the parentNodes
748 // 2. Construct correct URL and body using that data
749 // 3. Make the request to external HTTP endpoint using the URL and body
750 // 4. Decode the HTTP response
751 // 5. Run GraphQL completion on the decoded HTTP response
752 // 6. Create fastJson nodes which contain the completion result for this custom field for
753 // all the duplicate parents and
754 // 7. Update the fastJson tree with those fastJson nodes
755
756 var parentNodeHeadAttr uint16
757 if len(parentNodeHeads) > 0 {
758 parentNodeHeadAttr = genc.getAttr(parentNodeHeads[0])
759 }
760 isGraphqlReq := fconf.RemoteGqlQueryName != ""
761 requiredFields := childField.CustomRequiredFields()
762
763 // we need to find the ID or @id field from requiredFields as we want to make HTTP requests
764 // only for unique parent nodes. That means, we send/receive less data over the network,
765 // and thus minimize the network latency as much as possible.
766 idFieldName := ""
767 idFieldValue := ""
768 for _, fieldDef := range requiredFields {
769 if fieldDef.IsID() || fieldDef.HasIDDirective() {
770 idFieldName = fieldDef.Name()
771 break
772 }
773 }
774 if idFieldName == "" {
775 // This should not happen as we only allow custom fields which either use ID field or a
776 // field with @id directive.
777 genc.errCh <- x.GqlErrorList{childField.GqlErrorf(nil,
778 "unable to find a required field with type ID! or @id directive for @custom field %s.",
779 childField.Name())}
780 return
781 }
782
783 // we don't know the number of unique parents in advance,
784 // so can't allocate this list with a pre-defined size
785 var uniqueParents []interface{}
786 // uniqueParentIdxToIdFieldVal stores the idFieldValue for each unique rfData
787 var uniqueParentIdxToIdFieldVal []string
788 // parentNodes is a map from idFieldValue to all the parentNodes for that idFieldValue.
789 parentNodes := make(map[string][]fastJsonNode)
790
791 // Step-1: Find the requiredFields data for uniqueParents from all the parentNodes
792 for _, parentNodeHead := range parentNodeHeads {
793 // iterate over all the siblings of this parentNodeHead which have the same attr as this
794 for parentNode := parentNodeHead; parentNode != nil && genc.getAttr(

Callers 1

resolveCustomFieldsMethod · 0.95

Calls 15

getAttrMethod · 0.80
WaitMethod · 0.80
TypeOfMethod · 0.80
toStringFunction · 0.70
CustomHTTPConfigMethod · 0.65
GqlErrorfMethod · 0.65
CustomRequiredFieldsMethod · 0.65
IsIDMethod · 0.65
HasIDDirectiveMethod · 0.65
NameMethod · 0.65

Tested by

no test coverage detected